Improved Javascript decoder size + bugfixing

Changes:
1. Javascript decoder can now be built separately for meshes and point
clouds. Together with other optimizations this results in about 33%
smaller Javascript for mesh decoder. (pre-built javascript for meshes
and point clouds is included).

2. Fixing bug in our symbol_encoder that resulted in failed encoding for
certain cases when there were around 1<<18 symbols.

3. Changing default setting of our draco_encoder app to -cl 7
This commit is contained in:
Ondrej Stava 2017-03-08 15:39:24 -08:00
parent e85b83b16a
commit 59b297b18a
10 changed files with 163 additions and 28 deletions

View File

@ -9,6 +9,8 @@ include("${draco_root}/cmake/compiler_flags.cmake")
# Draco requires C++11 support.
require_cxx_flag_nomsvc("-std=c++11")
option(ENABLE_POINT_CLOUD_COMPRESSION "" ON)
option(ENABLE_MESH_COMPRESSION "" ON)
option(ENABLE_STANDARD_EDGEBREAKER "" ON)
option(ENABLE_PREDICTIVE_EDGEBREAKER "" ON)
option(ENABLE_EXTRA_WARNINGS "" OFF)
@ -17,6 +19,12 @@ option(ENABLE_WERROR "" OFF)
option(ENABLE_WEXTRA "" OFF)
option(IGNORE_EMPTY_BUILD_TYPE "" OFF)
if (ENABLE_POINT_CLOUD_COMPRESSION)
add_cxx_preproc_definition("DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED")
endif ()
if (ENABLE_MESH_COMPRESSION)
add_cxx_preproc_definition("DRACO_MESH_COMPRESSION_SUPPORTED")
endif ()
if (ENABLE_STANDARD_EDGEBREAKER)
add_cxx_preproc_definition("DRACO_STANDARD_EDGEBREAKER_SUPPORTED")
endif ()
@ -412,6 +420,11 @@ if (EMSCRIPTEN)
add_compiler_flag_if_supported("-s ALLOW_MEMORY_GROWTH=1")
add_compiler_flag_if_supported("--memory-init-file 0")
add_compiler_flag_if_supported("-fno-omit-frame-pointer")
add_compiler_flag_if_supported(-s MODULARIZE=1)
add_compiler_flag_if_supported(-s EXPORT_NAME="'DracoModule'")
add_compiler_flag_if_supported(--llvm-lto 1)
add_compiler_flag_if_supported(-s NO_FILESYSTEM=1)
add_compiler_flag_if_supported(-s ELIMINATE_DUPLICATE_FUNCTIONS=1)
if (CMAKE_BUILD_TYPE STREQUAL "")
# Force -O3 when no build type is specified.
@ -504,6 +517,18 @@ else ()
$<TARGET_OBJECTS:draco_mesh>
$<TARGET_OBJECTS:draco_point_cloud>
$<TARGET_OBJECTS:draco_points_decoder>)
add_library(dracoenc
${draco_version_sources}
$<TARGET_OBJECTS:draco_compression_attributes_encoder>
$<TARGET_OBJECTS:draco_compression_attributes_pred_schemes>
$<TARGET_OBJECTS:draco_compression_config>
$<TARGET_OBJECTS:draco_compression_encode>
$<TARGET_OBJECTS:draco_compression_mesh_encoder>
$<TARGET_OBJECTS:draco_compression_point_cloud_encoder>
$<TARGET_OBJECTS:draco_core>
$<TARGET_OBJECTS:draco_mesh>
$<TARGET_OBJECTS:draco_point_cloud>
$<TARGET_OBJECTS:draco_points_encoder>)
add_library(draco
${draco_version_sources}
$<TARGET_OBJECTS:draco_compression_attributes_decoder>

View File

@ -12,14 +12,26 @@ LD=emcc
DRACO_CONFIG ?= full
# Full config - all features included.
DRACO_FULL_CONFIG_DEFINES := -DDRACO_STANDARD_EDGEBREAKER_SUPPORTED
DRACO_FULL_CONFIG_DEFINES += -DDRACO_PREDICTIVE_EDGEBREAKER_SUPPORTED
DRACO_FULL_MESH_CONFIG_DEFINES := -DDRACO_MESH_COMPRESSION_SUPPORTED
DRACO_FULL_MESH_CONFIG_DEFINES += -DDRACO_STANDARD_EDGEBREAKER_SUPPORTED
DRACO_FULL_MESH_CONFIG_DEFINES += -DDRACO_PREDICTIVE_EDGEBREAKER_SUPPORTED
DRACO_FULL_POINT_CLOUD_CONFIG_DEFINES := -DDRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
DRACO_FULL_CONFIG_DEFINES := $(DRACO_FULL_MESH_CONFIG_DEFINES)
DRACO_FULL_CONFIG_DEFINES += $(DRACO_FULL_POINT_CLOUD_CONFIG_DEFINES)
# Default limited config with only some core features enabled.
DRACO_LIMITED_CONFIG_DEFINES := -DDRACO_STANDARD_EDGEBREAKER_SUPPORTED
DRACO_LIMITED_CONFIG_DEFINES += -DDRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
DRACO_LIMITED_CONFIG_DEFINES += -DDRACO_MESH_COMPRESSION_SUPPORTED
ifeq ($(DRACO_CONFIG), limited)
DRACO_CONFIG_DEFINES := $(DRACO_LIMITED_CONFIG_DEFINES)
else ifeq ($(DRACO_CONFIG), full_mesh)
DRACO_CONFIG_DEFINES := $(DRACO_FULL_MESH_CONFIG_DEFINES)
else ifeq ($(DRACO_CONFIG), full_point_cloud)
DRACO_CONFIG_DEFINES := $(DRACO_FULL_POINT_CLOUD_CONFIG_DEFINES)
else
DRACO_CONFIG_DEFINES := $(DRACO_FULL_CONFIG_DEFINES)
endif
@ -47,6 +59,8 @@ ALL_C_OPTS := -std=c++11
# Options for speed.
ALL_C_OPTS += -O3
ALL_C_OPTS += --llvm-lto 1 -s NO_FILESYSTEM=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1
ALL_C_OPTS += -s EXPORTED_RUNTIME_METHODS=[]
# Options for debug
#ALL_C_OPTS += -g -s DEMANGLE_SUPPORT=1

View File

@ -100,9 +100,11 @@ bool SequentialIntegerAttributeEncoder::EncodeValues(
if (encoder() == nullptr || encoder()->options()->GetGlobalBool(
"use_built_in_attribute_compression", true)) {
out_buffer->Encode(static_cast<uint8_t>(1));
EncodeSymbols(reinterpret_cast<uint32_t *>(values_.data()),
point_ids.size() * num_components, num_components,
out_buffer);
if (!EncodeSymbols(reinterpret_cast<uint32_t *>(values_.data()),
point_ids.size() * num_components, num_components,
out_buffer)) {
return false;
}
} else {
// No compression. Just store the raw integer values, using the number of
// bytes as needed.

View File

@ -15,10 +15,16 @@
#include "compression/decode.h"
#include "compression/config/compression_shared.h"
#ifdef DRACO_MESH_COMPRESSION_SUPPORTED
#include "compression/mesh/mesh_edgebreaker_decoder.h"
#include "compression/mesh/mesh_sequential_decoder.h"
#endif
#ifdef DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
#include "compression/point_cloud/point_cloud_kd_tree_decoder.h"
#include "compression/point_cloud/point_cloud_sequential_decoder.h"
#endif
namespace draco {
@ -56,6 +62,7 @@ EncodedGeometryType GetEncodedGeometryType(DecoderBuffer *in_buffer) {
return geom_type;
}
#ifdef DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
std::unique_ptr<PointCloudDecoder> CreatePointCloudDecoder(int8_t method) {
if (method == POINT_CLOUD_SEQUENTIAL_ENCODING) {
return std::unique_ptr<PointCloudDecoder>(
@ -65,7 +72,9 @@ std::unique_ptr<PointCloudDecoder> CreatePointCloudDecoder(int8_t method) {
}
return nullptr;
}
#endif
#ifdef DRACO_MESH_COMPRESSION_SUPPORTED
std::unique_ptr<MeshDecoder> CreateMeshDecoder(uint8_t method) {
if (method == MESH_SEQUENTIAL_ENCODING) {
return std::unique_ptr<MeshDecoder>(new MeshSequentialDecoder());
@ -74,6 +83,7 @@ std::unique_ptr<MeshDecoder> CreateMeshDecoder(uint8_t method) {
}
return nullptr;
}
#endif
std::unique_ptr<PointCloud> DecodePointCloudFromBuffer(
DecoderBuffer *in_buffer) {
@ -82,6 +92,7 @@ std::unique_ptr<PointCloud> DecodePointCloudFromBuffer(
if (!ParseHeader(in_buffer, &encoder_type, &method))
return nullptr;
if (encoder_type == POINT_CLOUD) {
#ifdef DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
std::unique_ptr<PointCloudDecoder> decoder =
CreatePointCloudDecoder(method);
if (!decoder)
@ -90,7 +101,9 @@ std::unique_ptr<PointCloud> DecodePointCloudFromBuffer(
if (!decoder->Decode(in_buffer, point_cloud.get()))
return nullptr;
return point_cloud;
#endif
} else if (encoder_type == TRIANGULAR_MESH) {
#ifdef DRACO_MESH_COMPRESSION_SUPPORTED
std::unique_ptr<MeshDecoder> decoder = CreateMeshDecoder(method);
if (!decoder)
return nullptr;
@ -98,11 +111,13 @@ std::unique_ptr<PointCloud> DecodePointCloudFromBuffer(
if (!decoder->Decode(in_buffer, mesh.get()))
return nullptr;
return std::move(mesh);
#endif
}
return nullptr;
}
std::unique_ptr<Mesh> DecodeMeshFromBuffer(DecoderBuffer *in_buffer) {
#ifdef DRACO_MESH_COMPRESSION_SUPPORTED
EncodedGeometryType encoder_type;
int8_t method;
if (!ParseHeader(in_buffer, &encoder_type, &method))
@ -117,6 +132,9 @@ std::unique_ptr<Mesh> DecodeMeshFromBuffer(DecoderBuffer *in_buffer) {
if (!decoder->Decode(in_buffer, mesh.get()))
return nullptr;
return mesh;
#else
return nullptr;
#endif
}
} // namespace draco

View File

@ -94,7 +94,7 @@ TEST_F(SymbolCodingTest, TestOneSymbol) {
}
}
TEST_F(SymbolCodingTest, TestBitLengthsl) {
TEST_F(SymbolCodingTest, TestBitLengths) {
// This test verifies that SymbolCoding successfully encodes symbols of
// various bitlengths
EncoderBuffer eb;
@ -116,4 +116,21 @@ TEST_F(SymbolCodingTest, TestBitLengthsl) {
}
}
TEST_F(SymbolCodingTest, TestLargeNumberCondition) {
// This test verifies that SymbolCoding successfully encodes large symbols
// that are on the boundary between raw scheme and tagged scheme (18 bits).
EncoderBuffer eb;
constexpr int num_symbols = 1000000;
const std::vector<uint32_t> in(num_symbols, 1 << 18);
ASSERT_TRUE(EncodeSymbols(in.data(), in.size(), 1, &eb));
std::vector<uint32_t> out(in.size());
DecoderBuffer db;
db.Init(eb.data(), eb.size());
ASSERT_TRUE(DecodeSymbols(in.size(), 1, &db, &out[0]));
for (uint32_t i = 0; i < in.size(); ++i) {
ASSERT_EQ(in[i], out[i]);
}
}
} // namespace draco

View File

@ -133,8 +133,7 @@ bool EncodeSymbols(const uint32_t *symbols, int num_values, int num_components,
// The maximum bit length of a single entry value that we can encode using
// the raw scheme.
const int max_value_bit_length = bits::MostSignificantBit(max_value);
const int max_value_bit_length = bits::MostSignificantBit(max_value) + 1;
if (tagged_scheme_total_bits < raw_scheme_total_bits ||
max_value_bit_length > kMaxRawEncodingBitLength) {
@ -266,7 +265,7 @@ bool EncodeRawSymbols(const uint32_t *symbols, int num_values,
max_value_bits = bits::MostSignificantBit(max_entry_value);
}
const int max_value_bit_length = max_value_bits + 1;
// Currently, we don't support encoding of values larger than 2^20.
// Currently, we don't support encoding of values larger than 2^18.
if (max_value_bit_length > kMaxRawEncodingBitLength)
return false;
target_buffer->Encode(static_cast<uint8_t>(max_value_bit_length));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -40,7 +40,7 @@ Options::Options()
pos_quantization_bits(14),
tex_coords_quantization_bits(12),
normals_quantization_bits(10),
compression_level(5) {}
compression_level(7) {}
void Usage() {
printf("Usage: draco_encoder [options] -i input\n");
@ -63,7 +63,7 @@ void Usage() {
"attribute, default=10.\n");
printf(
" -cl <value> compression level [0-10], most=10, least=0, "
"default=5.\n");
"default=7.\n");
}
int StringToInt(const std::string &s) {
@ -246,7 +246,18 @@ int main(int argc, char **argv) {
}
PrintOptions(*pc.get(), options);
int ret = -1;
if (mesh && mesh->num_faces() > 0)
return EncodeMeshToFile(*mesh, encoder_options, options.output);
return EncodePointCloudToFile(*pc.get(), encoder_options, options.output);
ret = EncodeMeshToFile(*mesh, encoder_options, options.output);
else
ret = EncodePointCloudToFile(*pc.get(), encoder_options, options.output);
if (ret != -1 && options.compression_level < 10) {
printf(
"For better compression, increase the compression level '-cl' (up to "
"10).\n\n");
}
return ret;
}