amd/vpelib: Add cache mechanism for 3D Lut command
[WHY & HOW] Converting 3D Lut parameters into vpe command takes time. 3D Lut will not change every frame, by adding cache mechanism can improve effeciency. Reviewed-by: Tomson Chang <tomson.chang@amd.com> Acked-by: Alan Liu <haoping.liu@amd.com> Signed-off-by: Mike Hsieh <mike.hsieh@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30715>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user