diff --git a/src/amd/vpelib/inc/vpe_types.h b/src/amd/vpelib/inc/vpe_types.h index c4e5c47292a..eb53720a64e 100644 --- a/src/amd/vpelib/inc/vpe_types.h +++ b/src/amd/vpelib/inc/vpe_types.h @@ -347,6 +347,7 @@ struct vpe_debug_options { uint32_t bg_bit_depth : 1; uint32_t visual_confirm : 1; uint32_t skip_optimal_tap_check : 1; + uint32_t disable_3dlut_cache : 1; } flags; // valid only if the corresponding flag is set @@ -369,6 +370,7 @@ struct vpe_debug_options { uint32_t opp_pipe_crc_ctrl : 1; uint32_t mpc_crc_ctrl : 1; uint32_t skip_optimal_tap_check : 1; + uint32_t disable_3dlut_cache : 1; uint32_t bg_bit_depth; struct vpe_mem_low_power_enable_options enable_mem_low_power; diff --git a/src/amd/vpelib/src/chip/vpe10/vpe10_mpc.c b/src/amd/vpelib/src/chip/vpe10/vpe10_mpc.c index d6cc30d7a74..94fd3c539ff 100644 --- a/src/amd/vpelib/src/chip/vpe10/vpe10_mpc.c +++ b/src/amd/vpelib/src/chip/vpe10/vpe10_mpc.c @@ -1258,11 +1258,55 @@ void vpe10_mpc_set_mpc_shaper_3dlut( mpc->funcs->program_shaper(mpc, shaper_lut); if (lut3d_func) { - if (lut3d_func->state.bits.initialized) - mpc->funcs->program_3dlut(mpc, &lut3d_func->lut_3d); - else + if (lut3d_func->state.bits.initialized) { + // check if 3D Lut cache enabled + PROGRAM_ENTRY(); + struct stream_ctx *stream_ctx = &vpe_priv->stream_ctx[vpe_priv->fe_cb_ctx.stream_idx]; + + if (mpc->vpe_priv->init.debug.disable_3dlut_cache || !stream_ctx->uid_3dlut || + !stream_ctx->lut3d_cache) { + mpc->funcs->program_3dlut(mpc, &lut3d_func->lut_3d); + } else { // 3D Lut cache enabled + + config_writer_force_new_with_type(config_writer, CONFIG_TYPE_DIRECT); + + // check cache status, if cache exist, use cache + if (stream_ctx->lut3d_cache->uid == stream_ctx->uid_3dlut && + config_writer->buf->size >= stream_ctx->lut3d_cache->buffer_size) { + memcpy((void *)(uintptr_t)config_writer->base_cpu_va, + stream_ctx->lut3d_cache->cache_buf, + stream_ctx->lut3d_cache->buffer_size); + config_writer->buf->cpu_va = config_writer->base_cpu_va + + stream_ctx->lut3d_cache->buffer_size; + config_writer->buf->gpu_va = config_writer->base_gpu_va + + stream_ctx->lut3d_cache->buffer_size; + config_writer->buf->size -= + (stream_ctx->lut3d_cache->buffer_size - sizeof(uint32_t)); + } else { // if cache not exist generate command and save to cache + uint64_t start, end; + + uint16_t config_num = stream_ctx->num_configs; + + start = config_writer->base_cpu_va; + mpc->funcs->program_3dlut(mpc, &lut3d_func->lut_3d); + end = config_writer->buf->cpu_va; + if (config_num == stream_ctx->num_configs) { // check if cross config + if ((end - start) <= VPE_3DLUT_CACHE_SIZE) { + stream_ctx->lut3d_cache->buffer_size = end - start; + memcpy(stream_ctx->lut3d_cache->cache_buf, (void *)(uintptr_t)start, + stream_ctx->lut3d_cache->buffer_size); + stream_ctx->lut3d_cache->uid = stream_ctx->uid_3dlut; + } + } else { // current cache does not support cross config + stream_ctx->lut3d_cache->uid = 0; + } + } + } + } else { mpc->funcs->program_3dlut(mpc, NULL); + } } + return; } diff --git a/src/amd/vpelib/src/core/color.c b/src/amd/vpelib/src/core/color.c index a61e218eeda..57089de7231 100644 --- a/src/amd/vpelib/src/core/color.c +++ b/src/amd/vpelib/src/core/color.c @@ -652,7 +652,7 @@ enum vpe_status vpe_color_update_color_space_and_tf( } bool is_3dlut_enable = stream_ctx->stream.tm_params.UID != 0 || stream_ctx->stream.tm_params.enable_3dlut; - bool require_update = stream_ctx->UID_3DLUT != param->streams[stream_idx].tm_params.UID; + bool require_update = stream_ctx->uid_3dlut != param->streams[stream_idx].tm_params.UID; color_check_input_cm_update(vpe_priv, stream_ctx, ¶m->streams[stream_idx].surface_info.cs, ¶m->streams[stream_idx].color_adj, @@ -762,7 +762,7 @@ enum vpe_status vpe_color_update_movable_cm( bool enable_3dlut = stream_ctx->stream.tm_params.UID != 0 || stream_ctx->stream.tm_params.enable_3dlut; - if (stream_ctx->UID_3DLUT != stream_ctx->stream.tm_params.UID) { + if (stream_ctx->uid_3dlut != stream_ctx->stream.tm_params.UID) { uint32_t shaper_norm_factor; struct vpe_color_space tm_out_cs; @@ -796,6 +796,19 @@ enum vpe_status vpe_color_update_movable_cm( } } + if (enable_3dlut) { + if (!stream_ctx->lut3d_cache) { // setup cache if needed + stream_ctx->lut3d_cache = vpe_zalloc(sizeof(struct vpe_3dlut_cache)); + if (!stream_ctx->lut3d_cache) { + vpe_log("err: out of memory for 3d lut cache!"); + ret = VPE_STATUS_NO_MEMORY; + goto exit; + } + stream_ctx->lut3d_cache->uid = 0; + } + // 3D Lut updated, invalid cache + } + if (!output_ctx->gamut_remap) { output_ctx->gamut_remap = vpe_zalloc(sizeof(struct colorspace_transform)); if (!output_ctx->gamut_remap) { @@ -807,8 +820,7 @@ enum vpe_status vpe_color_update_movable_cm( //Blendgam is updated by output vpe_update_output_gamma_sequence - get_shaper_norm_factor( - ¶m->streams[stream_idx].tm_params, stream_ctx, &shaper_norm_factor); + get_shaper_norm_factor(&stream_ctx->stream.tm_params, stream_ctx, &shaper_norm_factor); vpe_color_tm_update_hdr_mult(SHAPER_EXP_MAX_IN, shaper_norm_factor, &stream_ctx->lut3d_func->hdr_multiplier, enable_3dlut); @@ -822,10 +834,12 @@ enum vpe_status vpe_color_update_movable_cm( vpe_color_update_gamut(vpe_priv, out_lut_cs, vpe_priv->output_ctx.cs, output_ctx->gamut_remap, !enable_3dlut); - vpe_convert_to_tetrahedral(vpe_priv, param->streams[stream_idx].tm_params.lut_data, - stream_ctx->lut3d_func, enable_3dlut); + if ((enable_3dlut && !stream_ctx->stream.tm_params.UID) || + stream_ctx->lut3d_cache->uid != stream_ctx->stream.tm_params.UID) + vpe_convert_to_tetrahedral(vpe_priv, stream_ctx->stream.tm_params.lut_data, + stream_ctx->lut3d_func, enable_3dlut); - stream_ctx->UID_3DLUT = param->streams[stream_idx].tm_params.UID; + stream_ctx->uid_3dlut = stream_ctx->stream.tm_params.UID; } } exit: diff --git a/src/amd/vpelib/src/core/config_writer.c b/src/amd/vpelib/src/core/config_writer.c index 2b493b151fc..5a9c8fd2552 100644 --- a/src/amd/vpelib/src/core/config_writer.c +++ b/src/amd/vpelib/src/core/config_writer.c @@ -93,6 +93,26 @@ void config_writer_set_type(struct config_writer *writer, enum config_type type) } } +void config_writer_force_new_with_type(struct config_writer *writer, enum config_type type) +{ + VPE_ASSERT(type != CONFIG_TYPE_UNKNOWN); + + if (writer->status != VPE_STATUS_OK) + return; + + uint64_t size = writer->buf->cpu_va - writer->base_cpu_va; + + if (writer->type == CONFIG_TYPE_UNKNOWN) { + // new header. don't need to fill it yet until completion + config_writer_new(writer); + } else if (size > 0) { + // command not empty, close the previous one + config_writer_complete(writer); + config_writer_new(writer); + } + writer->type = type; +} + void config_writer_fill(struct config_writer *writer, uint32_t value) { uint32_t *cmd_space; diff --git a/src/amd/vpelib/src/core/inc/config_writer.h b/src/amd/vpelib/src/core/inc/config_writer.h index 1c233c873f6..c6ee05701d2 100644 --- a/src/amd/vpelib/src/core/inc/config_writer.h +++ b/src/amd/vpelib/src/core/inc/config_writer.h @@ -121,6 +121,20 @@ void config_writer_set_callback( */ void config_writer_set_type(struct config_writer *writer, enum config_type type); +/** force create new config with specific type + * if the config is empty, only type will be changed, otherwise create new one + * 1) direct config + * VPEP_DIRECT_CONFIG_ARRAY_SIZE is finalized (in DW0) automatically. + * 2) indirect config + * NUM_DST is finalized (in DW0) automatically. + * and run callback (if set) to notify the completion. + * A new config desc header DW0 will be generated. + * + * /param writer writer instance + * /param type config type + */ +void config_writer_force_new_with_type(struct config_writer *writer, enum config_type type); + /** fill the value to the buffer. * If the dword exceeds the config packet size limit, * callback will be called and a new config desc is created. diff --git a/src/amd/vpelib/src/core/inc/vpe_priv.h b/src/amd/vpelib/src/core/inc/vpe_priv.h index 39e521a9f15..81d222d62ee 100644 --- a/src/amd/vpelib/src/core/inc/vpe_priv.h +++ b/src/amd/vpelib/src/core/inc/vpe_priv.h @@ -104,7 +104,15 @@ struct vpe_cmd_info { struct config_record { uint64_t config_base_addr; - uint64_t config_size; + uint64_t config_size; +}; + +#define VPE_3DLUT_CACHE_SIZE 81920 + +struct vpe_3dlut_cache { + uint64_t uid; + uint8_t cache_buf[VPE_3DLUT_CACHE_SIZE]; + uint64_t buffer_size; }; /** represents a stream input, i.e. common to all segments */ @@ -128,7 +136,7 @@ struct stream_ctx { enum color_transfer_func tf; enum color_space cs; bool enable_3dlut; - uint64_t UID_3DLUT; // UID for current 3D LUT params + uint64_t uid_3dlut; // UID for current 3D LUT params bool geometric_scaling; bool is_yuv_input; @@ -148,6 +156,7 @@ struct stream_ctx { struct colorspace_transform *gamut_remap; struct transfer_func *in_shaper_func; // for shaper lut struct vpe_3dlut *lut3d_func; // for 3dlut + struct vpe_3dlut_cache *lut3d_cache; // for 3dlut cache struct transfer_func *blend_tf; // for 1dlut white_point_gain white_point_gain; diff --git a/src/amd/vpelib/src/core/resource.c b/src/amd/vpelib/src/core/resource.c index b74585e1c3d..d1c5c586d00 100644 --- a/src/amd/vpelib/src/core/resource.c +++ b/src/amd/vpelib/src/core/resource.c @@ -59,25 +59,26 @@ static const struct vpe_debug_options debug_defaults = { .mpc = false, }, }, - .expansion_mode = 1, - .clamping_setting = 1, + .expansion_mode = 1, + .clamping_setting = 1, .clamping_params = - { - .r_clamp_component_lower = 0x1000, - .g_clamp_component_lower = 0x1000, - .b_clamp_component_lower = 0x1000, - .r_clamp_component_upper = 0xEB00, - .g_clamp_component_upper = 0xEB00, - .b_clamp_component_upper = 0xEB00, - .clamping_range = 4, - }, - .bypass_per_pixel_alpha = 0, - .opp_pipe_crc_ctrl = 0, - .dpp_crc_ctrl = 0, - .mpc_crc_ctrl = 0, - .visual_confirm_params = {{{0}}}, - .skip_optimal_tap_check = 0, - .bypass_blndgam = 0 + { + .r_clamp_component_lower = 0x1000, + .g_clamp_component_lower = 0x1000, + .b_clamp_component_lower = 0x1000, + .r_clamp_component_upper = 0xEB00, + .g_clamp_component_upper = 0xEB00, + .b_clamp_component_upper = 0xEB00, + .clamping_range = 4, + }, + .bypass_per_pixel_alpha = 0, + .opp_pipe_crc_ctrl = 0, + .dpp_crc_ctrl = 0, + .mpc_crc_ctrl = 0, + .visual_confirm_params = {{{0}}}, + .skip_optimal_tap_check = 0, + .disable_3dlut_cache = 0, + .bypass_blndgam = 0 }; enum vpe_ip_level vpe_resource_parse_ip_version( @@ -183,7 +184,7 @@ struct stream_ctx *vpe_alloc_stream_ctx(struct vpe_priv *vpe_priv, uint32_t num_ ctx->tf_scaling_factor = vpe_fixpt_one; ctx->stream.flags.geometric_scaling = 0; ctx->stream.tm_params.UID = 0; - ctx->UID_3DLUT = 0; + ctx->uid_3dlut = 0; } return ctx_base; @@ -234,6 +235,11 @@ void vpe_free_stream_ctx(struct vpe_priv *vpe_priv) ctx->lut3d_func = NULL; } + if (ctx->lut3d_cache) { + vpe_free(ctx->lut3d_cache); + ctx->lut3d_cache = NULL; + } + if (ctx->segment_ctx) { vpe_free(ctx->segment_ctx); ctx->segment_ctx = NULL; diff --git a/src/amd/vpelib/src/core/vpelib.c b/src/amd/vpelib/src/core/vpelib.c index 00bf74a4db6..576f1a4b9cb 100644 --- a/src/amd/vpelib/src/core/vpelib.c +++ b/src/amd/vpelib/src/core/vpelib.c @@ -121,6 +121,9 @@ static void override_debug_option( if (user_debug->flags.bypass_blndgam) debug->bypass_blndgam = user_debug->bypass_blndgam; + + if (user_debug->flags.disable_3dlut_cache) + debug->disable_3dlut_cache = user_debug->disable_3dlut_cache; } #ifdef VPE_BUILD_1_1