| @@ -74,6 +74,7 @@ typedef struct VulkanEncodeFFv1Context { · 73 unmodified lines |
| 74 | 74 | size_t max_heap_size; |
| 75 | 75 | |
| 76 | 76 | FFVulkanShader setup; |
| 77 | + FFVulkanShader rct_search; |
| 77 | 78 | FFVulkanShader reset; |
| 78 | 79 | FFVulkanShader enc; |
| 79 | 80 | |
| @@ -101,6 +102,7 @@ typedef struct VulkanEncodeFFv1Context { · 21 unmodified lines |
| 101 | 102 | int num_h_slices; |
| 102 | 103 | int num_v_slices; |
| 103 | 104 | int force_pcm; |
| 105 | + int optimize_rct; |
| 104 | 106 | |
| 105 | 107 | int is_rgb; |
| 106 | 108 | int ppi; |
| @@ -112,6 +114,7 @@ extern const char *ff_source_rangecoder_comp; · 5 unmodified lines |
| 112 | 114 | extern const char *ff_source_ffv1_vlc_comp; |
| 113 | 115 | extern const char *ff_source_ffv1_common_comp; |
| 114 | 116 | extern const char *ff_source_ffv1_reset_comp; |
| 117 | +extern const char *ff_source_ffv1_rct_search_comp; |
| 115 | 118 | extern const char *ff_source_ffv1_enc_setup_comp; |
| 116 | 119 | extern const char *ff_source_ffv1_enc_comp; |
| 117 | 120 | |
| @@ -147,7 +150,8 @@ typedef struct FFv1VkParameters { · 29 unmodified lines |
| 147 | 150 | uint8_t ec; |
| 148 | 151 | uint8_t ppi; |
| 149 | 152 | uint8_t chunks; |
| 150 | | − uint8_t padding[4]; |
| 153 | + uint8_t rct_search; |
| 154 | + uint8_t padding[3]; |
| 151 | 155 | } FFv1VkParameters; |
| 152 | 156 | |
| 153 | 157 | static void add_push_data(FFVulkanShader *shd) |
| @@ -184,12 +188,76 @@ static void add_push_data(FFVulkanShader *shd) · 30 unmodified lines |
| 184 | 188 | GLSLC(1, uint8_t ec; ); |
| 185 | 189 | GLSLC(1, uint8_t ppi; ); |
| 186 | 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 | 193 | GLSLC(0, }; ); |
| 189 | 194 | ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkParameters), |
| 190 | 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 | 261 | static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx, |
| 194 | 262 | FFVkExecContext *exec, |
| 195 | 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 | 456 | vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) { |
| 370 | 457 | .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, |
| 371 | 458 | .pImageMemoryBarriers = img_bar, |
| @@ -412,6 +499,7 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx, · 40 unmodified lines |
| 412 | 499 | .ec = f->ec, |
| 413 | 500 | .ppi = fv->ppi, |
| 414 | 501 | .chunks = fv->chunks, |
| 502 | + .rct_search = fv->optimize_rct, |
| 415 | 503 | }; |
| 416 | 504 | |
| 417 | 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 | 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 | 1108 | static int init_setup_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv) |
| 924 | 1109 | { |
| 925 | 1110 | int err; |
| @@ -1417,6 +1602,17 @@ static av_cold int vulkan_encode_ffv1_init(AVCodecContext *avctx) · 491 unmodified lines |
| 1417 | 1602 | if (!fv->is_rgb && f->bits_per_raw_sample > 8) |
| 1418 | 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 | 1616 | /* Init setup shader */ |
| 1421 | 1617 | err = init_setup_shader(avctx, spv); |
| 1422 | 1618 | if (err < 0) { |
| @@ -1528,6 +1724,7 @@ static av_cold int vulkan_encode_ffv1_close(AVCodecContext *avctx) · 105 unmodified lines |
| 1528 | 1724 | ff_vk_shader_free(&fv->s, &fv->enc); |
| 1529 | 1725 | ff_vk_shader_free(&fv->s, &fv->reset); |
| 1530 | 1726 | ff_vk_shader_free(&fv->s, &fv->setup); |
| 1727 | + ff_vk_shader_free(&fv->s, &fv->rct_search); |
| 1531 | 1728 | |
| 1532 | 1729 | if (fv->exec_ctx_info) { |
| 1533 | 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 | 1788 | { "force_pcm", "Code all slices with no prediction", OFFSET(force_pcm), AV_OPT_TYPE_BOOL, |
| 1592 | 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 | 1794 | { "async_depth", "Internal parallelization depth", OFFSET(async_depth), AV_OPT_TYPE_INT, |
| 1595 | 1795 | { .i64 = 1 }, 1, INT_MAX, VE }, |
| 1596 | 1796 | |