Unified · Split
| @@ -112,6 +112,78 @@ static const char write_444[] = { · 111 unmodified lines | |||
| 112 | C(0, } ) | 112 | C(0, } ) |
| 113 | }; | 113 | }; |
| 114 | 114 | ||
| 115 | static int init_scale_shader(ScaleVulkanContext *s, FFVulkanShader *shd, | ||
| 116 | FFVulkanDescriptorSetBinding *desc, AVFrame *in) | ||
| 117 | { | ||
| 118 | GLSLD( scale_bilinear ); | ||
| 119 | |||
| 120 | if (s->vkctx.output_format != s->vkctx.input_format) { | ||
| 121 | GLSLD( rgb2yuv ); | ||
| 122 | } | ||
| 123 | |||
| 124 | switch (s->vkctx.output_format) { | ||
| 125 | case AV_PIX_FMT_NV12: GLSLD(write_nv12); break; | ||
| 126 | case AV_PIX_FMT_YUV420P: GLSLD( write_420); break; | ||
| 127 | case AV_PIX_FMT_YUV444P: GLSLD( write_444); break; | ||
| 128 | default: break; | ||
| 129 | } | ||
| 130 | |||
| 131 | GLSLC(0, void main() ); | ||
| 132 | GLSLC(0, { ); | ||
| 133 | GLSLC(1, ivec2 size; ); | ||
| 134 | GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); | ||
| 135 | GLSLF(1, vec2 in_d = vec2(%i, %i); ,in->width, in->height); | ||
| 136 | GLSLC(1, vec2 c_r = vec2(crop_w, crop_h) / in_d; ); | ||
| 137 | GLSLC(1, vec2 c_o = vec2(crop_x, crop_y) / in_d; ); | ||
| 138 | GLSLC(0, ); | ||
| 139 | |||
| 140 | if (s->vkctx.output_format == s->vkctx.input_format) { | ||
| 141 | for (int i = 0; i < desc[1].elems; i++) { | ||
| 142 | GLSLF(1, size = imageSize(output_img[%i]); ,i); | ||
| 143 | GLSLC(1, if (IS_WITHIN(pos, size)) { ); | ||
| 144 | switch (s->scaler) { | ||
| 145 | case F_NEAREST: | ||
| 146 | case F_BILINEAR: | ||
| 147 | GLSLF(2, vec4 res = scale_bilinear(%i, pos, c_r, c_o); ,i); | ||
| 148 | GLSLF(2, imageStore(output_img[%i], pos, res); ,i); | ||
| 149 | break; | ||
| 150 | }; | ||
| 151 | GLSLC(1, } ); | ||
| 152 | } | ||
| 153 | } else { | ||
| 154 | GLSLC(1, vec4 res = scale_bilinear(0, pos, c_r, c_o); ); | ||
| 155 | GLSLF(1, res = rgb2yuv(res, %i); ,s->out_range == AVCOL_RANGE_JPEG); | ||
| 156 | switch (s->vkctx.output_format) { | ||
| 157 | case AV_PIX_FMT_NV12: GLSLC(1, write_nv12(res, pos); ); break; | ||
| 158 | case AV_PIX_FMT_YUV420P: GLSLC(1, write_420(res, pos); ); break; | ||
| 159 | case AV_PIX_FMT_YUV444P: GLSLC(1, write_444(res, pos); ); break; | ||
| 160 | default: return AVERROR(EINVAL); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | GLSLC(0, } ); | ||
| 165 | |||
| 166 | if (s->vkctx.output_format != s->vkctx.input_format) { | ||
| 167 | const AVLumaCoefficients *lcoeffs; | ||
| 168 | double tmp_mat[3][3]; | ||
| 169 | |||
| 170 | lcoeffs = av_csp_luma_coeffs_from_avcsp(in->colorspace); | ||
| 171 | if (!lcoeffs) { | ||
| 172 | av_log(s, AV_LOG_ERROR, "Unsupported colorspace\n"); | ||
| 173 | return AVERROR(EINVAL); | ||
| 174 | } | ||
| 175 | |||
| 176 | ff_fill_rgb2yuv_table(lcoeffs, tmp_mat); | ||
| 177 | |||
| 178 | for (int y = 0; y < 3; y++) | ||
| 179 | for (int x = 0; x < 3; x++) | ||
| 180 | s->opts.yuv_matrix[x][y] = tmp_mat[x][y]; | ||
| 181 | s->opts.yuv_matrix[3][3] = 1.0; | ||
| 182 | } | ||
| 183 | |||
| 184 | return 0; | ||
| 185 | } | ||
| 186 | |||
| 115 | static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) | 187 | static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) |
| 116 | { | 188 | { |
| 117 | int err; | 189 | int err; |
| @@ -157,18 +229,6 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) · 39 unmodified lines | |||
| 157 | 32, 32, 1, | 229 | 32, 32, 1, |
| 158 | 0)); | 230 | 0)); |
| 159 | 231 | ||
| 160 | GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); | ||
| 161 | GLSLC(1, mat4 yuv_matrix; ); | ||
| 162 | GLSLC(1, int crop_x; ); | ||
| 163 | GLSLC(1, int crop_y; ); | ||
| 164 | GLSLC(1, int crop_w; ); | ||
| 165 | GLSLC(1, int crop_h; ); | ||
| 166 | GLSLC(0, }; ); | ||
| 167 | GLSLC(0, ); | ||
| 168 | |||
| 169 | ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts), | ||
| 170 | VK_SHADER_STAGE_COMPUTE_BIT); | ||
| 171 | |||
| 172 | desc = (FFVulkanDescriptorSetBinding []) { | 232 | desc = (FFVulkanDescriptorSetBinding []) { |
| 173 | { | 233 | { |
| 174 | .name = "input_img", | 234 | .name = "input_img", |
| @@ -191,71 +251,21 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) · 16 unmodified lines | |||
| 191 | 251 | ||
| 192 | RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0)); | 252 | RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0)); |
| 193 | 253 | ||
| 194 | GLSLD( scale_bilinear ); | 254 | GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); |
| 195 | 255 | GLSLC(1, mat4 yuv_matrix; ); | |
| 196 | if (s->vkctx.output_format != s->vkctx.input_format) { | 256 | GLSLC(1, int crop_x; ); |
| 197 | GLSLD( rgb2yuv ); | 257 | GLSLC(1, int crop_y; ); |
| 198 | } | 258 | GLSLC(1, int crop_w; ); |
| 199 | 259 | GLSLC(1, int crop_h; ); | |
| 200 | switch (s->vkctx.output_format) { | 260 | GLSLC(0, }; ); |
| 201 | case AV_PIX_FMT_NV12: GLSLD(write_nv12); break; | 261 | GLSLC(0, ); |
| 202 | case AV_PIX_FMT_YUV420P: GLSLD( write_420); break; | ||
| 203 | case AV_PIX_FMT_YUV444P: GLSLD( write_444); break; | ||
| 204 | default: break; | ||
| 205 | } | ||
| 206 | |||
| 207 | GLSLC(0, void main() ); | ||
| 208 | GLSLC(0, { ); | ||
| 209 | GLSLC(1, ivec2 size; ); | ||
| 210 | GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); | ||
| 211 | GLSLF(1, vec2 in_d = vec2(%i, %i); ,in->width, in->height); | ||
| 212 | GLSLC(1, vec2 c_r = vec2(crop_w, crop_h) / in_d; ); | ||
| 213 | GLSLC(1, vec2 c_o = vec2(crop_x, crop_y) / in_d; ); | ||
| 214 | GLSLC(0, ); | ||
| 215 | |||
| 216 | if (s->vkctx.output_format == s->vkctx.input_format) { | ||
| 217 | for (int i = 0; i < desc[1].elems; i++) { | ||
| 218 | GLSLF(1, size = imageSize(output_img[%i]); ,i); | ||
| 219 | GLSLC(1, if (IS_WITHIN(pos, size)) { ); | ||
| 220 | switch (s->scaler) { | ||
| 221 | case F_NEAREST: | ||
| 222 | case F_BILINEAR: | ||
| 223 | GLSLF(2, vec4 res = scale_bilinear(%i, pos, c_r, c_o); ,i); | ||
| 224 | GLSLF(2, imageStore(output_img[%i], pos, res); ,i); | ||
| 225 | break; | ||
| 226 | }; | ||
| 227 | GLSLC(1, } ); | ||
| 228 | } | ||
| 229 | } else { | ||
| 230 | GLSLC(1, vec4 res = scale_bilinear(0, pos, c_r, c_o); ); | ||
| 231 | GLSLF(1, res = rgb2yuv(res, %i); ,s->out_range == AVCOL_RANGE_JPEG); | ||
| 232 | switch (s->vkctx.output_format) { | ||
| 233 | case AV_PIX_FMT_NV12: GLSLC(1, write_nv12(res, pos); ); break; | ||
| 234 | case AV_PIX_FMT_YUV420P: GLSLC(1, write_420(res, pos); ); break; | ||
| 235 | case AV_PIX_FMT_YUV444P: GLSLC(1, write_444(res, pos); ); break; | ||
| 236 | default: return AVERROR(EINVAL); | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | GLSLC(0, } ); | ||
| 241 | |||
| 242 | if (s->vkctx.output_format != s->vkctx.input_format) { | ||
| 243 | const AVLumaCoefficients *lcoeffs; | ||
| 244 | double tmp_mat[3][3]; | ||
| 245 | |||
| 246 | lcoeffs = av_csp_luma_coeffs_from_avcsp(in->colorspace); | ||
| 247 | if (!lcoeffs) { | ||
| 248 | av_log(ctx, AV_LOG_ERROR, "Unsupported colorspace\n"); | ||
| 249 | return AVERROR(EINVAL); | ||
| 250 | } | ||
| 251 | 262 | ||
| 252 | ff_fill_rgb2yuv_table(lcoeffs, tmp_mat); | 263 | ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts), |
| 264 | VK_SHADER_STAGE_COMPUTE_BIT); | ||
| 253 | 265 | ||
| 254 | for (int y = 0; y < 3; y++) | 266 | err = init_scale_shader(s, shd, desc, in); |
| 255 | for (int x = 0; x < 3; x++) | 267 | if (err < 0) |
| 256 | s->opts.yuv_matrix[x][y] = tmp_mat[x][y]; | 268 | goto fail; |
| 257 | s->opts.yuv_matrix[3][3] = 1.0; | ||
| 258 | } | ||
| 259 | 269 | ||
| 260 | RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main", | 270 | RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main", |
| 261 | &spv_opaque)); | 271 | &spv_opaque)); |