History

transpose_vulkan: port for the rewrite

Lynne committed 3 years ago

Commit f70f8731 parent d4b51b51 file · +76 −148Browse files

Unified · Split

libavfilter/vf_transpose_vulkan.c+76−148
@@ -1,5 +1,7 @@
1/*1/*
2 * copyright (c) 2021 Wu Jianhua <jianhua.wu@intel.com>2 * copyright (c) 2021 Wu Jianhua <jianhua.wu@intel.com>
3 * Copyright (c) Lynne
4 *
3 * This file is part of FFmpeg.5 * This file is part of FFmpeg.
4 *6 *
5 * FFmpeg is free software; you can redistribute it and/or7 * FFmpeg is free software; you can redistribute it and/or
@@ -20,41 +22,60 @@ · 14 unmodified lines
20#include "libavutil/random_seed.h"22#include "libavutil/random_seed.h"
21#include "libavutil/opt.h"23#include "libavutil/opt.h"
22#include "vulkan_filter.h"24#include "vulkan_filter.h"
25#include "vulkan_spirv.h"
23#include "internal.h"26#include "internal.h"
24#include "transpose.h"27#include "transpose.h"
25 28
26#define CGS 32
27
28typedef struct TransposeVulkanContext {29typedef struct TransposeVulkanContext {
29 FFVulkanContext vkctx;30 FFVulkanContext vkctx;
30 FFVkQueueFamilyCtx qf;
31 FFVkExecContext *exec;
32 FFVulkanPipeline *pl;
33 31
34 VkDescriptorImageInfo input_images[3];32 int initialized;
35 VkDescriptorImageInfo output_images[3];33 FFVulkanPipeline pl;
34 FFVkExecPool e;
35 FFVkQueueFamilyCtx qf;
36 FFVkSPIRVShader shd;
37 VkSampler sampler;
36 38
37 int dir;39 int dir;
38 int passthrough;40 int passthrough;
39 int initialized;
40} TransposeVulkanContext;41} TransposeVulkanContext;
41 42
42static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)43static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
43{44{
44 int err = 0;45 int err;
45 FFVkSPIRVShader *shd;46 uint8_t *spv_data;
47 size_t spv_len;
48 void *spv_opaque = NULL;
46 TransposeVulkanContext *s = ctx->priv;49 TransposeVulkanContext *s = ctx->priv;
47 FFVulkanContext *vkctx = &s->vkctx;50 FFVulkanContext *vkctx = &s->vkctx;
51
48 const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);52 const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
53 FFVkSPIRVShader *shd = &s->shd;
54 FFVkSPIRVCompiler *spv;
55 FFVulkanDescriptorSetBinding *desc;
56
57 spv = ff_vk_spirv_init();
58 if (!spv) {
59 av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
60 return AVERROR_EXTERNAL;
61 }
62
63 ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT);
64 RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL));
65 RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_LINEAR));
66 RET(ff_vk_shader_init(&s->pl, &s->shd, "transpose_compute",
67 VK_SHADER_STAGE_COMPUTE_BIT, 0));
49 68
50 FFVulkanDescriptorSetBinding image_descs[] = {69 ff_vk_shader_set_compute_sizes(&s->shd, 32, 1, 1);
70
71 desc = (FFVulkanDescriptorSetBinding []) {
51 {72 {
52 .name = "input_images",73 .name = "input_images",
53 .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,74 .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
54 .dimensions = 2,75 .dimensions = 2,
55 .elems = planes,76 .elems = planes,
56 .stages = VK_SHADER_STAGE_COMPUTE_BIT,77 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
57 .updater = s->input_images,78 .samplers = DUP_SAMPLER(s->sampler),
58 },79 },
59 {80 {
60 .name = "output_images",81 .name = "output_images",
@@ -64,154 +85,49 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) · 3 unmodified lines
64 .dimensions = 2,85 .dimensions = 2,
65 .elems = planes,86 .elems = planes,
66 .stages = VK_SHADER_STAGE_COMPUTE_BIT,87 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
67 .updater = s->output_images,
68 },88 },
69 };89 };
70 90
71 image_descs[0].sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR);91 RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl, shd, desc, 2, 0, 0));
72 if (!image_descs[0].sampler)
73 return AVERROR_EXTERNAL;
74
75 ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
76
77 {
78 s->pl = ff_vk_create_pipeline(vkctx, &s->qf);
79 if (!s->pl)
80 return AVERROR(ENOMEM);
81
82 shd = ff_vk_init_shader(s->pl, "transpose_compute", image_descs[0].stages);
83 if (!shd)
84 return AVERROR(ENOMEM);
85
86 ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 });
87 RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0));
88
89 GLSLC(0, void main() );
90 GLSLC(0, { );
91 GLSLC(1, ivec2 size; );
92 GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); );
93 for (int i = 0; i < planes; i++) {
94 GLSLC(0, );
95 GLSLF(1, size = imageSize(output_images[%i]); ,i);
96 GLSLC(1, if (IS_WITHIN(pos, size)) { );
97 if (s->dir == TRANSPOSE_CCLOCK)
98 GLSLF(2, vec4 res = texture(input_images[%i], ivec2(size.y - pos.y, pos.x)); ,i);
99 else if (s->dir == TRANSPOSE_CLOCK_FLIP || s->dir == TRANSPOSE_CLOCK) {
100 GLSLF(2, vec4 res = texture(input_images[%i], ivec2(size.yx - pos.yx)); ,i);
101 if (s->dir == TRANSPOSE_CLOCK)
102 GLSLC(2, pos = ivec2(pos.x, size.y - pos.y); );
103 } else
104 GLSLF(2, vec4 res = texture(input_images[%i], pos.yx); ,i);
105 GLSLF(2, imageStore(output_images[%i], pos, res); ,i);
106 GLSLC(1, } );
107 }
108 GLSLC(0, } );
109
110 RET(ff_vk_compile_shader(vkctx, shd, "main"));
111 RET(ff_vk_init_pipeline_layout(vkctx, s->pl));
112 RET(ff_vk_init_compute_pipeline(vkctx, s->pl));
113 }
114
115 RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf));
116 s->initialized = 1;
117
118fail:
119 return err;
120}
121
122static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *inframe)
123{
124 int err = 0;
125 VkCommandBuffer cmd_buf;
126 TransposeVulkanContext *s = avctx->priv;
127 FFVulkanContext *vkctx = &s->vkctx;
128 FFVulkanFunctions *vk = &s->vkctx.vkfn;
129 const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
130
131 AVVkFrame *in = (AVVkFrame *)inframe->data[0];
132 AVVkFrame *out = (AVVkFrame *)outframe->data[0];
133
134 const VkFormat *input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format);
135 const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format);
136
137 ff_vk_start_exec_recording(vkctx, s->exec);
138 cmd_buf = ff_vk_get_exec_buf(s->exec);
139
140 for (int i = 0; i < planes; i++) {
141 RET(ff_vk_create_imageview(vkctx, s->exec,
142 &s->input_images[i].imageView, in->img[i],
143 input_formats[i],
144 ff_comp_identity_map));
145
146 RET(ff_vk_create_imageview(vkctx, s->exec,
147 &s->output_images[i].imageView, out->img[i],
148 output_formats[i],
149 ff_comp_identity_map));
150
151 s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
152 s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
153 }
154
155 ff_vk_update_descriptor_set(vkctx, s->pl, 0);
156 92
93 GLSLC(0, void main() );
94 GLSLC(0, { );
95 GLSLC(1, ivec2 size; );
96 GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); );
157 for (int i = 0; i < planes; i++) {97 for (int i = 0; i < planes; i++) {
158 VkImageMemoryBarrier barriers[] = {98 GLSLC(0, );
159 {99 GLSLF(1, size = imageSize(output_images[%i]); ,i);
160 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,100 GLSLC(1, if (IS_WITHIN(pos, size)) { );
161 .srcAccessMask = 0,101 if (s->dir == TRANSPOSE_CCLOCK)
162 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT,102 GLSLF(2, vec4 res = texture(input_images[%i], ivec2(size.y - pos.y, pos.x)); ,i);
163 .oldLayout = in->layout[i],103 else if (s->dir == TRANSPOSE_CLOCK_FLIP || s->dir == TRANSPOSE_CLOCK) {
164 .newLayout = s->input_images[i].imageLayout,104 GLSLF(2, vec4 res = texture(input_images[%i], ivec2(size.yx - pos.yx)); ,i);
165 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,105 if (s->dir == TRANSPOSE_CLOCK)
166 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,106 GLSLC(2, pos = ivec2(pos.x, size.y - pos.y); );
167 .image = in->img[i],107 } else
168 .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,108 GLSLF(2, vec4 res = texture(input_images[%i], pos.yx); ,i);
169 .subresourceRange.levelCount = 1,109 GLSLF(2, imageStore(output_images[%i], pos, res); ,i);
170 .subresourceRange.layerCount = 1,110 GLSLC(1, } );
171 },
172 {
173 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
174 .srcAccessMask = 0,
175 .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
176 .oldLayout = out->layout[i],
177 .newLayout = s->output_images[i].imageLayout,
178 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
179 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
180 .image = out->img[i],
181 .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
182 .subresourceRange.levelCount = 1,
183 .subresourceRange.layerCount = 1,
184 },
185 };
186
187 vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
188 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0,
189 0, NULL, 0, NULL, FF_ARRAY_ELEMS(barriers), barriers);
190
191 in->layout[i] = barriers[0].newLayout;
192 in->access[i] = barriers[0].dstAccessMask;
193
194 out->layout[i] = barriers[1].newLayout;
195 out->access[i] = barriers[1].dstAccessMask;
196 }111 }
112 GLSLC(0, } );
197 113
198 ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl);114 RET(spv->compile_shader(spv, ctx, shd, &spv_data, &spv_len, "main",
199 vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS,115 &spv_opaque));
200 s->vkctx.output_height, 1);116 RET(ff_vk_shader_create(vkctx, shd, spv_data, spv_len, "main"));
201 117
202 ff_vk_add_exec_dep(vkctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);118 RET(ff_vk_init_compute_pipeline(vkctx, &s->pl, shd));
203 ff_vk_add_exec_dep(vkctx, s->exec, outframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);119 RET(ff_vk_exec_pipeline_register(vkctx, &s->e, &s->pl));
204 120
205 err = ff_vk_submit_exec_queue(vkctx, s->exec);121 s->initialized = 1;
206 if (err)
207 return err;
208
209 ff_vk_qf_rotate(&s->qf);
210 122
211 return 0;123 return 0;
212 124
213fail:125fail:
214 ff_vk_discard_exec_deps(s->exec);126 if (spv_opaque)
127 spv->free_shader(spv, &spv_opaque);
128 if (spv)
129 spv->uninit(&spv);
130
215 return err;131 return err;
216}132}
217 133
@@ -235,7 +151,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 17 unmodified lines
235 if (!s->initialized)151 if (!s->initialized)
236 RET(init_filter(ctx, in));152 RET(init_filter(ctx, in));
237 153
238 RET(process_frames(ctx, out, in));154 RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->pl, out, in,
155 s->sampler, NULL, 0));
239 156
240 RET(av_frame_copy_props(out, in));157 RET(av_frame_copy_props(out, in));
241 158
@@ -259,6 +176,17 @@ fail: · 17 unmodified lines
259static av_cold void transpose_vulkan_uninit(AVFilterContext *avctx)176static av_cold void transpose_vulkan_uninit(AVFilterContext *avctx)
260{177{
261 TransposeVulkanContext *s = avctx->priv;178 TransposeVulkanContext *s = avctx->priv;
179 FFVulkanContext *vkctx = &s->vkctx;
180 FFVulkanFunctions *vk = &vkctx->vkfn;
181
182 ff_vk_exec_pool_free(vkctx, &s->e);
183 ff_vk_pipeline_free(vkctx, &s->pl);
184 ff_vk_shader_free(vkctx, &s->shd);
185
186 if (s->sampler)
187 vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler,
188 vkctx->hwctx->alloc);
189
262 ff_vk_uninit(&s->vkctx);190 ff_vk_uninit(&s->vkctx);
263 191
264 s->initialized = 0;192 s->initialized = 0;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t