Skip to content

Commit

Permalink
feat(compression): add timing stats for high level compression passes
Browse files Browse the repository at this point in the history
Fixes #105
  • Loading branch information
nfrechette committed Feb 4, 2024
1 parent 24ccda4 commit 6f468b6
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 24 deletions.
20 changes: 19 additions & 1 deletion includes/acl/compression/impl/compact.transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
#include "acl/core/track_formats.h"
#include "acl/core/impl/compiler_utils.h"
#include "acl/core/error.h"
#include "acl/core/scope_profiler.h"
#include "acl/compression/impl/clip_context.h"
#include "acl/compression/impl/compression_stats.h"
#include "acl/compression/impl/rigid_shell_utils.h"
#include "acl/compression/transform_error_metrics.h"

Expand Down Expand Up @@ -349,8 +351,20 @@ namespace acl
// By default, constant sub-tracks will retain the first sample.
// A constant sub-track is a default sub-track if its unique sample can be replaced by the default value
// without exceeding our error threshold.
inline void compact_constant_streams(iallocator& allocator, clip_context& context, const clip_context& additive_base_clip_context, const track_array_qvvf& track_list, const compression_settings& settings)
inline void compact_constant_streams(
iallocator& allocator,
clip_context& context,
const clip_context& additive_base_clip_context,
const track_array_qvvf& track_list,
const compression_settings& settings,
compression_stats_t& compression_stats)
{
(void)compression_stats;

#if defined(ACL_USE_SJSON)
scope_profiler compact_constant_sub_tracks_time;
#endif

ACL_ASSERT(context.num_segments == 1, "context must contain a single segment!");

segment_context& segment = context.segments[0];
Expand Down Expand Up @@ -655,6 +669,10 @@ namespace acl
}
}
#endif

#if defined(ACL_USE_SJSON)
compression_stats.compact_constant_sub_tracks_elapsed_seconds = compact_constant_sub_tracks_time.get_elapsed_seconds();
#endif
}
}

Expand Down
40 changes: 28 additions & 12 deletions includes/acl/compression/impl/compress.transform.impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "acl/compression/output_stats.h"
#include "acl/compression/track_array.h"
#include "acl/compression/impl/clip_context.h"
#include "acl/compression/impl/compression_stats.h"
#include "acl/compression/impl/track_stream.h"
#include "acl/compression/impl/convert_rotation.transform.h"
#include "acl/compression/impl/compact.transform.h"
Expand Down Expand Up @@ -142,8 +143,12 @@ namespace acl
if (result.any())
return result;

compression_stats_t compression_stats;
(void)compression_stats;

#if defined(ACL_USE_SJSON)
scope_profiler compression_time;
scope_profiler initialization_time;
#endif

// Segmenting settings are an implementation detail
Expand Down Expand Up @@ -223,40 +228,44 @@ namespace acl
if (is_additive)
additive_base_clip_context.clip_shell_metadata = clip_shell_metadata;

#if defined(ACL_USE_SJSON)
compression_stats.initialization_elapsed_seconds = initialization_time.get_elapsed_seconds();
#endif

// Wrap instead of clamp if we loop
optimize_looping(lossy_clip_context, additive_base_clip_context, settings);
optimize_looping(lossy_clip_context, additive_base_clip_context, settings, compression_stats);

// Convert our rotations if we need to
convert_rotation_streams(allocator, lossy_clip_context, settings.rotation_format);
convert_rotation_streams(allocator, lossy_clip_context, settings.rotation_format, compression_stats);

// Extract our clip ranges now, we need it for compacting the constant streams
extract_clip_bone_ranges(allocator, lossy_clip_context);
extract_clip_bone_ranges(allocator, lossy_clip_context, compression_stats);

// Compact and collapse the constant streams
compact_constant_streams(allocator, lossy_clip_context, additive_base_clip_context, track_list, settings);
compact_constant_streams(allocator, lossy_clip_context, additive_base_clip_context, track_list, settings, compression_stats);

uint32_t clip_range_data_size = 0;
if (range_reduction != range_reduction_flags8::none)
{
// Normalize our samples into the clip wide ranges per bone
normalize_clip_streams(lossy_clip_context, range_reduction);
normalize_clip_streams(lossy_clip_context, range_reduction, compression_stats);
clip_range_data_size = get_clip_range_data_size(lossy_clip_context, range_reduction, settings.rotation_format);
}

segment_streams(allocator, lossy_clip_context, segmenting_settings);
segment_streams(allocator, lossy_clip_context, segmenting_settings, compression_stats);

// If we have a single segment, skip segment range reduction since it won't help
if (range_reduction != range_reduction_flags8::none && lossy_clip_context.num_segments > 1)
{
// Extract and fixup our segment wide ranges per bone
extract_segment_bone_ranges(allocator, lossy_clip_context);
extract_segment_bone_ranges(allocator, lossy_clip_context, compression_stats);

// Normalize our samples into the segment wide ranges per bone
normalize_segment_streams(lossy_clip_context, range_reduction);
normalize_segment_streams(lossy_clip_context, range_reduction, compression_stats);
}

// Find how many bits we need per sub-track and quantize everything
quantize_streams(allocator, lossy_clip_context, settings, raw_clip_context, additive_base_clip_context, out_stats);
quantize_streams(allocator, lossy_clip_context, settings, raw_clip_context, additive_base_clip_context, out_stats, compression_stats);

uint32_t num_output_bones = 0;
uint32_t* output_bone_mapping = create_output_track_mapping(allocator, track_list, num_output_bones);
Expand All @@ -265,9 +274,12 @@ namespace acl
calculate_animated_data_size(lossy_clip_context, output_bone_mapping, num_output_bones);

// Remove whole keyframes as needed
strip_keyframes(lossy_clip_context, settings);
strip_keyframes(lossy_clip_context, settings, compression_stats);

// Compression is done! Time to pack things.
#if defined(ACL_USE_SJSON)
scope_profiler output_packing_time;
#endif

if (remove_contributing_error)
settings.metadata.include_contributing_error = false;
Expand Down Expand Up @@ -517,6 +529,10 @@ namespace acl
buffer_header->size = buffer_size;
buffer_header->hash = hash32(safe_ptr_cast<const uint8_t>(header), buffer_size - sizeof(raw_buffer_header)); // Hash everything but the raw buffer header

#if defined(ACL_USE_SJSON)
compression_stats.output_packing_elapsed_seconds = output_packing_time.get_elapsed_seconds();
#endif

#if defined(ACL_HAS_ASSERT_CHECKS)
{
// Make sure we wrote the right amount of data
Expand Down Expand Up @@ -575,10 +591,10 @@ namespace acl
#endif

#if defined(ACL_USE_SJSON)
compression_time.stop();
compression_stats.total_elapsed_seconds = compression_time.stop().get_elapsed_seconds();

if (out_stats.logging != stat_logging::none)
write_stats(allocator, track_list, lossy_clip_context, *out_compressed_tracks, settings, segmenting_settings, range_reduction, raw_clip_context, additive_base_clip_context, compression_time, out_stats);
write_stats(allocator, track_list, lossy_clip_context, *out_compressed_tracks, settings, segmenting_settings, range_reduction, raw_clip_context, additive_base_clip_context, compression_stats, out_stats);
#endif

deallocate_type_array(allocator, output_bone_mapping, num_output_bones);
Expand Down
67 changes: 67 additions & 0 deletions includes/acl/compression/impl/compression_stats.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#pragma once

////////////////////////////////////////////////////////////////////////////////
// The MIT License (MIT)
//
// Copyright (c) 2024 Nicholas Frechette & Animation Compression Library contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
////////////////////////////////////////////////////////////////////////////////

#include "acl/version.h"
#include "acl/core/impl/compiler_utils.h"

#include <cstdint>

ACL_IMPL_FILE_PRAGMA_PUSH

namespace acl
{
ACL_IMPL_VERSION_NAMESPACE_BEGIN

namespace acl_impl
{
// Holds compression timing stats for diagnostics
struct compression_stats_t
{
#if defined(ACL_USE_SJSON)
// Total compression time
double total_elapsed_seconds = 0.0;

// High level passes
double initialization_elapsed_seconds = 0.0;
double optimize_looping_elapsed_seconds = 0.0;
double convert_rotations_elapsed_seconds = 0.0;
double extract_clip_ranges_elapsed_seconds = 0.0;
double compact_constant_sub_tracks_elapsed_seconds = 0.0;
double normalize_clip_elapsed_seconds = 0.0;
double segmenting_elapsed_seconds = 0.0;
double extract_segment_ranges_elapsed_seconds = 0.0;
double normalize_segment_elapsed_seconds = 0.0;
double bit_rate_optimization_elapsed_seconds = 0.0;
double keyframe_stripping_elapsed_seconds = 0.0;
double output_packing_elapsed_seconds = 0.0;
#endif
};
}

ACL_IMPL_VERSION_NAMESPACE_END
}

ACL_IMPL_FILE_PRAGMA_POP
18 changes: 17 additions & 1 deletion includes/acl/compression/impl/convert_rotation.transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@
#include "acl/core/iallocator.h"
#include "acl/core/impl/compiler_utils.h"
#include "acl/core/error.h"
#include "acl/core/scope_profiler.h"
#include "acl/core/track_formats.h"
#include "acl/compression/impl/clip_context.h"
#include "acl/compression/impl/compression_stats.h"

#include <rtm/quatf.h>
#include <rtm/vector4f.h>
Expand Down Expand Up @@ -105,10 +107,24 @@ namespace acl
}
}

inline void convert_rotation_streams(iallocator& allocator, clip_context& context, rotation_format8 rotation_format)
inline void convert_rotation_streams(
iallocator& allocator,
clip_context& context,
rotation_format8 rotation_format,
compression_stats_t& compression_stats)
{
(void)compression_stats;

#if defined(ACL_USE_SJSON)
scope_profiler convert_rotations_time;
#endif

for (segment_context& segment : context.segment_iterator())
convert_rotation_streams(allocator, segment, rotation_format);

#if defined(ACL_USE_SJSON)
compression_stats.convert_rotations_elapsed_seconds = convert_rotations_time.get_elapsed_seconds();
#endif
}
}

Expand Down
14 changes: 13 additions & 1 deletion includes/acl/compression/impl/keyframe_stripping.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
////////////////////////////////////////////////////////////////////////////////

#include "acl/version.h"
#include "acl/core/scope_profiler.h"
#include "acl/core/impl/compiler_utils.h"
#include "acl/compression/compression_settings.h"
#include "acl/compression/impl/compression_stats.h"

#include <cstdint>

Expand All @@ -38,11 +40,17 @@ namespace acl

namespace acl_impl
{
inline void strip_keyframes(clip_context& lossy_clip_context, const compression_settings& settings)
inline void strip_keyframes(clip_context& lossy_clip_context, const compression_settings& settings, compression_stats_t& compression_stats)
{
if (!settings.keyframe_stripping.is_enabled())
return; // We don't want to strip keyframes, nothing to do

(void)compression_stats;

#if defined(ACL_USE_SJSON)
scope_profiler keyframe_stripping_time;
#endif

const bitset_description hard_keyframes_desc = bitset_description::make_from_num_bits<32>();
const uint32_t num_keyframes = lossy_clip_context.num_samples;

Expand Down Expand Up @@ -130,6 +138,10 @@ namespace acl
}

lossy_clip_context.has_stripped_keyframes = num_keyframes_to_strip != 0;

#if defined(ACL_USE_SJSON)
compression_stats.keyframe_stripping_elapsed_seconds = keyframe_stripping_time.get_elapsed_seconds();
#endif
}
}

Expand Down
Loading

0 comments on commit 6f468b6

Please sign in to comment.