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:
Hsieh, Mike
2024-05-03 16:49:03 +08:00
committed by Marge Bot
parent 9817793cd9
commit 0164bfda65
8 changed files with 143 additions and 31 deletions
+2
View File
@@ -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;
+47 -3
View File
@@ -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;
}
+21 -7
View File
@@ -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,
&param->streams[stream_idx].surface_info.cs, &param->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(
&param->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:
+20
View File
@@ -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.
+11 -2
View File
@@ -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;
+25 -19
View File
@@ -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;
+3
View File
@@ -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