| @@ -74,6 +74,7 @@ typedef struct VulkanEncodeFFv1Context { · 73 unmodified lines |
| 74 | size_t max_heap_size; | 74 | size_t max_heap_size; |
| 75 | | 75 | |
| 76 | FFVulkanShader setup; | 76 | FFVulkanShader setup; |
| | 77 | FFVulkanShader rct_search; |
| 77 | FFVulkanShader reset; | 78 | FFVulkanShader reset; |
| 78 | FFVulkanShader enc; | 79 | FFVulkanShader enc; |
| 79 | | 80 | |
| @@ -101,6 +102,7 @@ typedef struct VulkanEncodeFFv1Context { · 21 unmodified lines |
| 101 | int num_h_slices; | 102 | int num_h_slices; |
| 102 | int num_v_slices; | 103 | int num_v_slices; |
| 103 | int force_pcm; | 104 | int force_pcm; |
| | 105 | int optimize_rct; |
| 104 | | 106 | |
| 105 | int is_rgb; | 107 | int is_rgb; |
| 106 | int ppi; | 108 | int ppi; |
| @@ -112,6 +114,7 @@ extern const char *ff_source_rangecoder_comp; · 5 unmodified lines |
| 112 | extern const char *ff_source_ffv1_vlc_comp; | 114 | extern const char *ff_source_ffv1_vlc_comp; |
| 113 | extern const char *ff_source_ffv1_common_comp; | 115 | extern const char *ff_source_ffv1_common_comp; |
| 114 | extern const char *ff_source_ffv1_reset_comp; | 116 | extern const char *ff_source_ffv1_reset_comp; |
| | 117 | extern const char *ff_source_ffv1_rct_search_comp; |
| 115 | extern const char *ff_source_ffv1_enc_setup_comp; | 118 | extern const char *ff_source_ffv1_enc_setup_comp; |
| 116 | extern const char *ff_source_ffv1_enc_comp; | 119 | extern const char *ff_source_ffv1_enc_comp; |
| 117 | | 120 | |
| @@ -147,7 +150,8 @@ typedef struct FFv1VkParameters { · 29 unmodified lines |
| 147 | uint8_t ec; | 150 | uint8_t ec; |
| 148 | uint8_t ppi; | 151 | uint8_t ppi; |
| 149 | uint8_t chunks; | 152 | uint8_t chunks; |
| 150 | uint8_t padding[4]; | 153 | uint8_t rct_search; |
| | 154 | uint8_t padding[3]; |
| 151 | } FFv1VkParameters; | 155 | } FFv1VkParameters; |
| 152 | | 156 | |
| 153 | static void add_push_data(FFVulkanShader *shd) | 157 | static void add_push_data(FFVulkanShader *shd) |
| @@ -184,12 +188,76 @@ static void add_push_data(FFVulkanShader *shd) · 30 unmodified lines |
| 184 | GLSLC(1, uint8_t ec; ); | 188 | GLSLC(1, uint8_t ec; ); |
| 185 | GLSLC(1, uint8_t ppi; ); | 189 | GLSLC(1, uint8_t ppi; ); |
| 186 | GLSLC(1, uint8_t chunks; ); | 190 | GLSLC(1, uint8_t chunks; ); |
| 187 | GLSLC(1, uint8_t padding[4]; ); | 191 | GLSLC(1, uint8_t rct_search; ); |
| | 192 | GLSLC(1, uint8_t padding[3]; ); |
| 188 | GLSLC(0, }; ); | 193 | GLSLC(0, }; ); |
| 189 | ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkParameters), | 194 | ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkParameters), |
| 190 | VK_SHADER_STAGE_COMPUTE_BIT); | 195 | VK_SHADER_STAGE_COMPUTE_BIT); |
| 191 | } | 196 | } |
| 192 | | 197 | |
| | 198 | typedef struct FFv1VkRCTSearchParameters { |
| | 199 | int fmt_lut[4]; |
| | 200 | int rct_offset; |
| | 201 | uint8_t planar_rgb; |
| | 202 | uint8_t transparency; |
| | 203 | uint8_t key_frame; |
| | 204 | uint8_t force_pcm; |
| | 205 | uint8_t version; |
| | 206 | uint8_t micro_version; |
| | 207 | uint8_t padding[2]; |
| | 208 | } FFv1VkRCTSearchParameters; |
| | 209 | |
| | 210 | static int run_rct_search(AVCodecContext *avctx, FFVkExecContext *exec, |
| | 211 | AVFrame *enc_in, VkImageView *enc_in_views, |
| | 212 | FFVkBuffer *slice_data_buf, uint32_t slice_data_size) |
| | 213 | { |
| | 214 | VulkanEncodeFFv1Context *fv = avctx->priv_data; |
| | 215 | FFV1Context *f = &fv->ctx; |
| | 216 | FFVulkanFunctions *vk = &fv->s.vkfn; |
| | 217 | AVHWFramesContext *src_hwfc = (AVHWFramesContext *)enc_in->hw_frames_ctx->data; |
| | 218 | FFv1VkRCTSearchParameters pd; |
| | 219 | |
| | 220 | /* Update descriptors */ |
| | 221 | ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->rct_search, |
| | 222 | 0, 0, 0, |
| | 223 | slice_data_buf, |
| | 224 | 0, slice_data_size*f->slice_count, |
| | 225 | VK_FORMAT_UNDEFINED); |
| | 226 | ff_vk_shader_update_img_array(&fv->s, exec, &fv->rct_search, |
| | 227 | enc_in, enc_in_views, |
| | 228 | 0, 1, |
| | 229 | VK_IMAGE_LAYOUT_GENERAL, |
| | 230 | VK_NULL_HANDLE); |
| | 231 | |
| | 232 | ff_vk_exec_bind_shader(&fv->s, exec, &fv->rct_search); |
| | 233 | |
| | 234 | pd = (FFv1VkRCTSearchParameters) { |
| | 235 | .rct_offset = 1 << f->bits_per_raw_sample, |
| | 236 | .planar_rgb = ff_vk_mt_is_np_rgb(src_hwfc->sw_format) && |
| | 237 | (ff_vk_count_images((AVVkFrame *)enc_in->data[0]) > 1), |
| | 238 | .transparency = f->transparency, |
| | 239 | .key_frame = f->key_frame, |
| | 240 | .force_pcm = fv->force_pcm, |
| | 241 | .version = f->version, |
| | 242 | .micro_version = f->micro_version, |
| | 243 | }; |
| | 244 | |
| | 245 | if (avctx->sw_pix_fmt == AV_PIX_FMT_GBRP10 || |
| | 246 | avctx->sw_pix_fmt == AV_PIX_FMT_GBRP12 || |
| | 247 | avctx->sw_pix_fmt == AV_PIX_FMT_GBRP14) |
| | 248 | memcpy(pd.fmt_lut, (int [4]) { 2, 1, 0, 3 }, 4*sizeof(int)); |
| | 249 | else |
| | 250 | ff_vk_set_perm(avctx->sw_pix_fmt, pd.fmt_lut, 1); |
| | 251 | |
| | 252 | ff_vk_shader_update_push_const(&fv->s, exec, &fv->rct_search, |
| | 253 | VK_SHADER_STAGE_COMPUTE_BIT, |
| | 254 | 0, sizeof(pd), &pd); |
| | 255 | |
| | 256 | vk->CmdDispatch(exec->buf, fv->ctx.num_h_slices, fv->ctx.num_v_slices, 1); |
| | 257 | |
| | 258 | return 0; |
| | 259 | } |
| | 260 | |
| 193 | static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx, | 261 | static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx, |
| 194 | FFVkExecContext *exec, | 262 | FFVkExecContext *exec, |
| 195 | const AVFrame *pict) | 263 | const AVFrame *pict) |
| @@ -366,6 +434,25 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx, · 170 unmodified lines |
| 366 | }; | 434 | }; |
| 367 | } | 435 | } |
| 368 | | 436 | |
| | 437 | if (fv->optimize_rct) { |
| | 438 | RET(run_rct_search(avctx, exec, |
| | 439 | src, src_views, |
| | 440 | slice_data_buf, slice_data_size)); |
| | 441 | |
| | 442 | buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) { |
| | 443 | .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, |
| | 444 | .srcStageMask = slice_data_buf->stage, |
| | 445 | .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, |
| | 446 | .srcAccessMask = slice_data_buf->access, |
| | 447 | .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, |
| | 448 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, |
| | 449 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, |
| | 450 | .buffer = slice_data_buf->buf, |
| | 451 | .size = slice_data_size*f->slice_count, |
| | 452 | .offset = 0, |
| | 453 | }; |
| | 454 | } |
| | 455 | |
| 369 | vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) { | 456 | vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) { |
| 370 | .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, | 457 | .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, |
| 371 | .pImageMemoryBarriers = img_bar, | 458 | .pImageMemoryBarriers = img_bar, |
| @@ -412,6 +499,7 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx, · 40 unmodified lines |
| 412 | .ec = f->ec, | 499 | .ec = f->ec, |
| 413 | .ppi = fv->ppi, | 500 | .ppi = fv->ppi, |
| 414 | .chunks = fv->chunks, | 501 | .chunks = fv->chunks, |
| | 502 | .rct_search = fv->optimize_rct, |
| 415 | }; | 503 | }; |
| 416 | | 504 | |
| 417 | /* For some reason the C FFv1 encoder/decoder treats these differently */ | 505 | /* For some reason the C FFv1 encoder/decoder treats these differently */ |
| @@ -920,6 +1008,103 @@ static void define_shared_code(AVCodecContext *avctx, FFVulkanShader *shd) · 502 unmodified lines |
| 920 | GLSLD(ff_source_ffv1_common_comp); | 1008 | GLSLD(ff_source_ffv1_common_comp); |
| 921 | } | 1009 | } |
| 922 | | 1010 | |
| | 1011 | static int init_rct_search_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv) |
| | 1012 | { |
| | 1013 | int err; |
| | 1014 | VulkanEncodeFFv1Context *fv = avctx->priv_data; |
| | 1015 | FFVulkanShader *shd = &fv->rct_search; |
| | 1016 | FFVulkanDescriptorSetBinding *desc_set; |
| | 1017 | |
| | 1018 | uint8_t *spv_data; |
| | 1019 | size_t spv_len; |
| | 1020 | void *spv_opaque = NULL; |
| | 1021 | |
| | 1022 | RET(ff_vk_shader_init(&fv->s, shd, "ffv1_rct_search", |
| | 1023 | VK_SHADER_STAGE_COMPUTE_BIT, |
| | 1024 | (const char *[]) { "GL_EXT_buffer_reference", |
| | 1025 | "GL_EXT_buffer_reference2", |
| | 1026 | "GL_EXT_null_initializer" }, 3, |
| | 1027 | 32, 32, 1, |
| | 1028 | 0)); |
| | 1029 | |
| | 1030 | /* Common codec header */ |
| | 1031 | GLSLD(ff_source_common_comp); |
| | 1032 | |
| | 1033 | GLSLC(0, layout(push_constant, scalar) uniform pushConstants { ); |
| | 1034 | GLSLC(1, ivec4 fmt_lut; ); |
| | 1035 | GLSLC(1, int rct_offset; ); |
| | 1036 | GLSLC(1, uint8_t planar_rgb; ); |
| | 1037 | GLSLC(1, uint8_t transparency; ); |
| | 1038 | GLSLC(1, uint8_t key_frame; ); |
| | 1039 | GLSLC(1, uint8_t force_pcm; ); |
| | 1040 | GLSLC(1, uint8_t version; ); |
| | 1041 | GLSLC(1, uint8_t micro_version; ); |
| | 1042 | GLSLC(1, uint8_t padding[3]; ); |
| | 1043 | GLSLC(0, }; ); |
| | 1044 | ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkResetParameters), |
| | 1045 | VK_SHADER_STAGE_COMPUTE_BIT); |
| | 1046 | |
| | 1047 | av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES); |
| | 1048 | av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS); |
| | 1049 | av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE); |
| | 1050 | |
| | 1051 | /* Never used */ |
| | 1052 | desc_set = (FFVulkanDescriptorSetBinding []) { |
| | 1053 | { |
| | 1054 | .name = "rangecoder_static_buf", |
| | 1055 | .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, |
| | 1056 | .stages = VK_SHADER_STAGE_COMPUTE_BIT, |
| | 1057 | .mem_layout = "scalar", |
| | 1058 | .buf_content = "uint8_t zero_one_state[512];", |
| | 1059 | }, |
| | 1060 | { |
| | 1061 | .name = "quant_buf", |
| | 1062 | .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, |
| | 1063 | .stages = VK_SHADER_STAGE_COMPUTE_BIT, |
| | 1064 | .mem_layout = "scalar", |
| | 1065 | .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]" |
| | 1066 | "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];", |
| | 1067 | }, |
| | 1068 | }; |
| | 1069 | RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 1, 1)); |
| | 1070 | |
| | 1071 | define_shared_code(avctx, shd); |
| | 1072 | |
| | 1073 | desc_set = (FFVulkanDescriptorSetBinding []) { |
| | 1074 | { |
| | 1075 | .name = "slice_data_buf", |
| | 1076 | .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, |
| | 1077 | .stages = VK_SHADER_STAGE_COMPUTE_BIT, |
| | 1078 | .buf_content = "SliceContext slice_ctx[1024];", |
| | 1079 | }, |
| | 1080 | { |
| | 1081 | .name = "src", |
| | 1082 | .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, |
| | 1083 | .dimensions = 2, |
| | 1084 | .mem_layout = ff_vk_shader_rep_fmt(fv->s.frames->sw_format, |
| | 1085 | fv->rep_fmt), |
| | 1086 | .elems = av_pix_fmt_count_planes(fv->s.frames->sw_format), |
| | 1087 | .mem_quali = "readonly", |
| | 1088 | .stages = VK_SHADER_STAGE_COMPUTE_BIT, |
| | 1089 | }, |
| | 1090 | }; |
| | 1091 | RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 0, 0)); |
| | 1092 | |
| | 1093 | GLSLD(ff_source_ffv1_rct_search_comp); |
| | 1094 | |
| | 1095 | RET(spv->compile_shader(&fv->s, spv, shd, &spv_data, &spv_len, "main", |
| | 1096 | &spv_opaque)); |
| | 1097 | RET(ff_vk_shader_link(&fv->s, shd, spv_data, spv_len, "main")); |
| | 1098 | |
| | 1099 | RET(ff_vk_shader_register_exec(&fv->s, &fv->exec_pool, shd)); |
| | 1100 | |
| | 1101 | fail: |
| | 1102 | if (spv_opaque) |
| | 1103 | spv->free_shader(spv, &spv_opaque); |
| | 1104 | |
| | 1105 | return err; |
| | 1106 | } |
| | 1107 | |
| 923 | static int init_setup_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv) | 1108 | static int init_setup_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv) |
| 924 | { | 1109 | { |
| 925 | int err; | 1110 | int err; |
| @@ -1417,6 +1602,17 @@ static av_cold int vulkan_encode_ffv1_init(AVCodecContext *avctx) · 491 unmodified lines |
| 1417 | if (!fv->is_rgb && f->bits_per_raw_sample > 8) | 1602 | if (!fv->is_rgb && f->bits_per_raw_sample > 8) |
| 1418 | fv->rep_fmt = FF_VK_REP_INT; | 1603 | fv->rep_fmt = FF_VK_REP_INT; |
| 1419 | | 1604 | |
| | 1605 | /* Init rct search shader */ |
| | 1606 | fv->optimize_rct = fv->is_rgb && f->version >= 4 && |
| | 1607 | !fv->force_pcm && fv->optimize_rct; |
| | 1608 | if (fv->optimize_rct) { |
| | 1609 | err = init_rct_search_shader(avctx, spv); |
| | 1610 | if (err < 0) { |
| | 1611 | spv->uninit(&spv); |
| | 1612 | return err; |
| | 1613 | } |
| | 1614 | } |
| | 1615 | |
| 1420 | /* Init setup shader */ | 1616 | /* Init setup shader */ |
| 1421 | err = init_setup_shader(avctx, spv); | 1617 | err = init_setup_shader(avctx, spv); |
| 1422 | if (err < 0) { | 1618 | if (err < 0) { |
| @@ -1528,6 +1724,7 @@ static av_cold int vulkan_encode_ffv1_close(AVCodecContext *avctx) · 105 unmodified lines |
| 1528 | ff_vk_shader_free(&fv->s, &fv->enc); | 1724 | ff_vk_shader_free(&fv->s, &fv->enc); |
| 1529 | ff_vk_shader_free(&fv->s, &fv->reset); | 1725 | ff_vk_shader_free(&fv->s, &fv->reset); |
| 1530 | ff_vk_shader_free(&fv->s, &fv->setup); | 1726 | ff_vk_shader_free(&fv->s, &fv->setup); |
| | 1727 | ff_vk_shader_free(&fv->s, &fv->rct_search); |
| 1531 | | 1728 | |
| 1532 | if (fv->exec_ctx_info) { | 1729 | if (fv->exec_ctx_info) { |
| 1533 | for (int i = 0; i < fv->async_depth; i++) { | 1730 | for (int i = 0; i < fv->async_depth; i++) { |
| @@ -1591,6 +1788,9 @@ static const AVOption vulkan_encode_ffv1_options[] = { · 57 unmodified lines |
| 1591 | { "force_pcm", "Code all slices with no prediction", OFFSET(force_pcm), AV_OPT_TYPE_BOOL, | 1788 | { "force_pcm", "Code all slices with no prediction", OFFSET(force_pcm), AV_OPT_TYPE_BOOL, |
| 1592 | { .i64 = 0 }, 0, 1, VE }, | 1789 | { .i64 = 0 }, 0, 1, VE }, |
| 1593 | | 1790 | |
| | 1791 | { "rct_search", "Run a search for RCT parameters (level 4 only)", OFFSET(optimize_rct), AV_OPT_TYPE_BOOL, |
| | 1792 | { .i64 = 1 }, 0, 1, VE }, |
| | 1793 | |
| 1594 | { "async_depth", "Internal parallelization depth", OFFSET(async_depth), AV_OPT_TYPE_INT, | 1794 | { "async_depth", "Internal parallelization depth", OFFSET(async_depth), AV_OPT_TYPE_INT, |
| 1595 | { .i64 = 1 }, 1, INT_MAX, VE }, | 1795 | { .i64 = 1 }, 1, INT_MAX, VE }, |
| 1596 | | 1796 | |