From: Steinar H. Gunderson Date: Mon, 15 Jan 2018 20:45:52 +0000 (+0100) Subject: Refactor calculate_scaling_weights() so that it is possible to get weights without... X-Git-Tag: 1.6.0~7 X-Git-Url: https://git.sesse.net/?p=movit;a=commitdiff_plain;h=f8e5ddc082f2267198292ea9e53d4a8b45f7b3b1 Refactor calculate_scaling_weights() so that it is possible to get weights without bilinear optimization. --- diff --git a/resample_effect.cpp b/resample_effect.cpp index b6da2e2..802a896 100644 --- a/resample_effect.cpp +++ b/resample_effect.cpp @@ -502,7 +502,7 @@ void SingleResamplePassEffect::update_texture(GLuint glsl_program_num, const str assert(false); } - ScalingWeights weights = calculate_scaling_weights(src_size, dst_size, zoom, offset); + ScalingWeights weights = calculate_bilinear_scaling_weights(src_size, dst_size, zoom, offset); src_bilinear_samples = weights.src_bilinear_samples; num_loops = weights.num_loops; slice_height = 1.0f / weights.num_loops; @@ -529,6 +529,8 @@ void SingleResamplePassEffect::update_texture(GLuint glsl_program_num, const str tex.update(weights.src_bilinear_samples, weights.dst_samples, internal_format, GL_RG, type, pixels); } +namespace { + ScalingWeights calculate_scaling_weights(unsigned src_size, unsigned dst_size, float zoom, float offset) { // Only needed if run from outside ResampleEffect. @@ -627,16 +629,33 @@ ScalingWeights calculate_scaling_weights(unsigned src_size, unsigned dst_size, f } } + ScalingWeights ret; + ret.src_bilinear_samples = src_samples; + ret.dst_samples = dst_samples; + ret.num_loops = num_loops; + ret.bilinear_weights_fp16 = nullptr; + ret.bilinear_weights_fp32 = move(weights); + return ret; +} + +} // namespace + +ScalingWeights calculate_bilinear_scaling_weights(unsigned src_size, unsigned dst_size, float zoom, float offset) +{ + ScalingWeights ret = calculate_scaling_weights(src_size, dst_size, zoom, offset); + unique_ptr[]> weights = move(ret.bilinear_weights_fp32); + const int src_samples = ret.src_bilinear_samples; + // Now make use of the bilinear filtering in the GPU to reduce the number of samples // we need to make. Try fp16 first; if it's not accurate enough, we go to fp32. // Our tolerance level for total error is a bit higher than the one for invididual // samples, since one would assume overall errors in the shape don't matter as much. const float max_error = 2.0f / (255.0f * 255.0f); unique_ptr[]> bilinear_weights_fp16; - int src_bilinear_samples = combine_many_samples(weights.get(), src_size, src_samples, dst_samples, &bilinear_weights_fp16); + int src_bilinear_samples = combine_many_samples(weights.get(), src_size, src_samples, ret.dst_samples, &bilinear_weights_fp16); unique_ptr[]> bilinear_weights_fp32 = nullptr; double max_sum_sq_error_fp16 = 0.0; - for (unsigned y = 0; y < dst_samples; ++y) { + for (unsigned y = 0; y < ret.dst_samples; ++y) { double sum_sq_error_fp16 = compute_sum_sq_error( weights.get() + y * src_samples, src_samples, bilinear_weights_fp16.get() + y * src_bilinear_samples, src_bilinear_samples, @@ -649,13 +668,10 @@ ScalingWeights calculate_scaling_weights(unsigned src_size, unsigned dst_size, f if (max_sum_sq_error_fp16 > max_error) { bilinear_weights_fp16.reset(); - src_bilinear_samples = combine_many_samples(weights.get(), src_size, src_samples, dst_samples, &bilinear_weights_fp32); + src_bilinear_samples = combine_many_samples(weights.get(), src_size, src_samples, ret.dst_samples, &bilinear_weights_fp32); } - ScalingWeights ret; ret.src_bilinear_samples = src_bilinear_samples; - ret.dst_samples = dst_samples; - ret.num_loops = num_loops; ret.bilinear_weights_fp16 = move(bilinear_weights_fp16); ret.bilinear_weights_fp32 = move(bilinear_weights_fp32); return ret; diff --git a/resample_effect.h b/resample_effect.h index 027a497..6a96ded 100644 --- a/resample_effect.h +++ b/resample_effect.h @@ -44,7 +44,7 @@ struct ScalingWeights { std::unique_ptr[]> bilinear_weights_fp16; std::unique_ptr[]> bilinear_weights_fp32; }; -ScalingWeights calculate_scaling_weights(unsigned src_size, unsigned dst_size, float zoom, float offset); +ScalingWeights calculate_bilinear_scaling_weights(unsigned src_size, unsigned dst_size, float zoom, float offset); // A simple manager for support data stored in a 2D texture. // Consider moving it to a shared location of more classes diff --git a/resample_effect_test.cpp b/resample_effect_test.cpp index a51c51d..16bd70c 100644 --- a/resample_effect_test.cpp +++ b/resample_effect_test.cpp @@ -480,7 +480,7 @@ BENCHMARK_CAPTURE(BM_ResampleEffectHalf, Float16Upscale, GAMMA_LINEAR, "fragment BENCHMARK_CAPTURE(BM_ResampleEffectInt8, Int8Downscale, GAMMA_REC_709, "fragment")->Args({1280, 720, 640, 360})->Args({1280, 720, 320, 180})->Args({1280, 720, 321, 181})->UseRealTime()->Unit(benchmark::kMicrosecond); BENCHMARK_CAPTURE(BM_ResampleEffectHalf, Float16Downscale, GAMMA_LINEAR, "fragment")->Args({1280, 720, 640, 360})->Args({1280, 720, 320, 180})->Args({1280, 720, 321, 181})->UseRealTime()->Unit(benchmark::kMicrosecond); -void BM_ComputeScalingWeights(benchmark::State &state) +void BM_ComputeBilinearScalingWeights(benchmark::State &state) { constexpr unsigned src_size = 1280; constexpr unsigned dst_size = 35; @@ -488,15 +488,15 @@ void BM_ComputeScalingWeights(benchmark::State &state) movit_texel_subpixel_precision = 64; // To get consistent results across GPUs; this is a CPU test. // One iteration warmup to make sure the Lanczos table is computed. - calculate_scaling_weights(src_size, dst_size, 0.999f, 0.0f); + calculate_bilinear_scaling_weights(src_size, dst_size, 0.999f, 0.0f); for (auto _ : state) { - ScalingWeights weights = calculate_scaling_weights(src_size, dst_size, 0.999f, 0.0f); + ScalingWeights weights = calculate_bilinear_scaling_weights(src_size, dst_size, 0.999f, 0.0f); } movit_texel_subpixel_precision = old_precision; } -BENCHMARK(BM_ComputeScalingWeights)->Unit(benchmark::kMicrosecond); +BENCHMARK(BM_ComputeBilinearScalingWeights)->Unit(benchmark::kMicrosecond); #endif