From 29d05cdd2285f546e8a7dec90bdb9244c14284e2 Mon Sep 17 00:00:00 2001 From: Cong Nguyen Date: Wed, 7 Mar 2018 17:36:15 +0700 Subject: [PATCH] support encode/decode attributes parallely --- .../attributes/sequential_attribute_decoder.h | 12 ++++ ...equential_attribute_decoders_controller.cc | 50 +++++++++++++++- .../attributes/sequential_attribute_encoder.h | 8 +++ ...equential_attribute_encoders_controller.cc | 58 +++++++++++++++++-- src/draco/psy/psy_draco.h | 21 ++++++- src/draco/psy/psy_draco_encoder.cpp | 14 +++++ 6 files changed, 155 insertions(+), 8 deletions(-) diff --git a/src/draco/compression/attributes/sequential_attribute_decoder.h b/src/draco/compression/attributes/sequential_attribute_decoder.h index 7a89fbb8..168cf1d5 100644 --- a/src/draco/compression/attributes/sequential_attribute_decoder.h +++ b/src/draco/compression/attributes/sequential_attribute_decoder.h @@ -37,6 +37,16 @@ class SequentialAttributeDecoder { virtual bool DecodePortableAttribute(const std::vector &point_ids, DecoderBuffer *in_buffer); + virtual void PrepareDecodingPortableAttribute(const size_t data_size, DecoderBuffer *in_buffer) { + mBuffer.Init(in_buffer->data_head(), data_size, in_buffer->bitstream_version()); + in_buffer->Advance(data_size); + } + + // Performs lossless decoding of the portable attribute data. + virtual bool DecodePortableAttribute(const std::vector &point_ids) { + return DecodePortableAttribute(point_ids, &mBuffer); + } + // Decodes any data needed to revert portable transform of the decoded // attribute. virtual bool DecodeDataNeededByPortableTransform( @@ -71,6 +81,8 @@ class SequentialAttributeDecoder { PointAttribute *portable_attribute() { return portable_attribute_.get(); } + DecoderBuffer mBuffer; + private: PointCloudDecoder *decoder_; PointAttribute *attribute_; diff --git a/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc b/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc index e653efa2..3a21d79a 100644 --- a/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc +++ b/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc @@ -17,8 +17,29 @@ #include "draco/compression/attributes/sequential_quantization_attribute_decoder.h" #include "draco/compression/config/compression_shared.h" +#include "draco/psy/psy_draco.h" + namespace draco { +class DecodePortableAttributeJob : public IDracoJob +{ +public: + DecodePortableAttributeJob() : mpDecoder(nullptr), mpPointIds(nullptr) {} + DecodePortableAttributeJob(SequentialAttributeDecoder* pDecoder, std::vector* pPointIds) + : mpDecoder(pDecoder), mpPointIds(pPointIds) { + } + + bool DoJob() override { + if (mpDecoder && mpPointIds) { + return mpDecoder->DecodePortableAttribute(*mpPointIds); + } + return false; + } + + SequentialAttributeDecoder* mpDecoder; + std::vector* mpPointIds; +}; + SequentialAttributeDecodersController::SequentialAttributeDecodersController( std::unique_ptr sequencer) : sequencer_(std::move(sequencer)) {} @@ -61,12 +82,35 @@ bool SequentialAttributeDecodersController::DecodeAttributes( bool SequentialAttributeDecodersController::DecodePortableAttributes( DecoderBuffer *in_buffer) { + PSY_DRACO_PROFILE_SECTION("DecodePortableAttributes()"); const int32_t num_attributes = GetNumAttributes(); - for (int i = 0; i < num_attributes; ++i) { - if (!sequential_decoders_[i]->DecodePortableAttribute(point_ids_, - in_buffer)) + std::vector encoded_blob_sizes(num_attributes, 0); + if (!in_buffer->Decode(encoded_blob_sizes.data(), num_attributes * sizeof(size_t))) { return false; } + + for (int i = 0; i < num_attributes; ++i) { + sequential_decoders_[i]->PrepareDecodingPortableAttribute(encoded_blob_sizes[i], in_buffer); + } + + if (num_attributes > 1 && psy::GetJobsParallelController()) { + auto p_controller = psy::GetJobsParallelController(); + std::vector> jobs(num_attributes); + std::vector p_jobs(num_attributes, nullptr); + for (uint32_t i = 0; i < num_attributes; ++i) { + jobs[i].reset(new DecodePortableAttributeJob(sequential_decoders_[i].get(), &point_ids_)); + p_jobs[i] = jobs[i].get(); + } + if (!p_controller->RunJobsParallely(p_jobs.data(), num_attributes)) { + return false; + } + } else { + for (int i = 0; i < num_attributes; ++i) { + if (!sequential_decoders_[i]->DecodePortableAttribute(point_ids_)) + return false; + } + } + return true; } diff --git a/src/draco/compression/attributes/sequential_attribute_encoder.h b/src/draco/compression/attributes/sequential_attribute_encoder.h index 325a7cda..2e8bde1d 100644 --- a/src/draco/compression/attributes/sequential_attribute_encoder.h +++ b/src/draco/compression/attributes/sequential_attribute_encoder.h @@ -53,6 +53,12 @@ class SequentialAttributeEncoder { virtual bool EncodePortableAttribute(const std::vector &point_ids, EncoderBuffer *out_buffer); + // Performs lossless encoding of the transformed attribute data. + virtual bool EncodePortableAttribute(const std::vector &point_ids) { + mBuffer.Resize(0); + return EncodePortableAttribute(point_ids, &mBuffer); + } + // Encodes any data related to the portable attribute transform. virtual bool EncodeDataNeededByPortableTransform(EncoderBuffer *out_buffer); @@ -79,6 +85,8 @@ class SequentialAttributeEncoder { int attribute_id() const { return attribute_id_; } PointCloudEncoder *encoder() const { return encoder_; } + EncoderBuffer mBuffer; + protected: // Should be used to initialize newly created prediction scheme. // Returns false when the initialization failed (in which case the scheme diff --git a/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc b/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc index d01d70d0..e529ab47 100644 --- a/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc +++ b/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc @@ -17,8 +17,30 @@ #include "draco/compression/attributes/sequential_quantization_attribute_encoder.h" #include "draco/compression/point_cloud/point_cloud_encoder.h" + +#include "draco/psy/psy_draco.h" + namespace draco { +class EncodePortableAttributeJob : public IDracoJob +{ +public: + EncodePortableAttributeJob() : mpEncoder(nullptr), mpPointIds(nullptr) {} + EncodePortableAttributeJob(SequentialAttributeEncoder* pEncoder, std::vector* pPointIds) + : mpEncoder(pEncoder), mpPointIds(pPointIds) { + } + + bool DoJob() override { + if (mpEncoder && mpPointIds) { + return (mpEncoder->EncodePortableAttribute(*mpPointIds)); + } + return (false); + } + + SequentialAttributeEncoder* mpEncoder; + std::vector* mpPointIds; +}; + SequentialAttributeEncodersController::SequentialAttributeEncodersController( std::unique_ptr sequencer) : sequencer_(std::move(sequencer)) {} @@ -72,11 +94,39 @@ bool SequentialAttributeEncodersController:: bool SequentialAttributeEncodersController::EncodePortableAttributes( EncoderBuffer *out_buffer) { - for (uint32_t i = 0; i < sequential_encoders_.size(); ++i) { - if (!sequential_encoders_[i]->EncodePortableAttribute(point_ids_, - out_buffer)) - return false; + PSY_DRACO_PROFILE_SECTION("EncodePortableAttributes()"); + + const auto encoders_count = sequential_encoders_.size(); + + if (encoders_count > 1 && psy::GetJobsParallelController()) { + auto p_controller = psy::GetJobsParallelController(); + std::vector> jobs(encoders_count); + std::vector p_jobs(encoders_count, nullptr); + for (uint32_t i = 0; i < encoders_count; ++i) { + jobs[i].reset(new EncodePortableAttributeJob(sequential_encoders_[i].get(), &point_ids_)); + p_jobs[i] = jobs[i].get(); + } + if (!p_controller->RunJobsParallely(p_jobs.data(), encoders_count)) { + return false; + } + } else { + for (uint32_t i = 0; i < encoders_count; ++i) { + if (!sequential_encoders_[i]->EncodePortableAttribute(point_ids_)) { + return false; + } + } + } + + for (uint32_t i = 0; i < encoders_count; ++i) { + if (!out_buffer->Encode(sequential_encoders_[i]->mBuffer.size())) { + return false; + } } + + for (uint32_t i = 0; i < encoders_count; ++i) { + out_buffer->Encode(sequential_encoders_[i]->mBuffer.data(), sequential_encoders_[i]->mBuffer.size()); + } + return true; } diff --git a/src/draco/psy/psy_draco.h b/src/draco/psy/psy_draco.h index f6d2b428..cafcbae8 100644 --- a/src/draco/psy/psy_draco.h +++ b/src/draco/psy/psy_draco.h @@ -37,12 +37,28 @@ class PSY_DRACO_API IProfilerManager virtual ~IProfilerManager() {} }; +class PSY_DRACO_API IDracoJob +{ +public: + virtual bool DoJob() = 0; + virtual ~IDracoJob() {} +}; +class PSY_DRACO_API IDracoJobsController +{ +public: + virtual bool RunJobsParallely(IDracoJob** pJobs, const size_t jobsCount) const = 0; + virtual ~IDracoJobsController() {} +}; + namespace psy { PSY_DRACO_API IProfilerManager* GetProfilerManager(); PSY_DRACO_API void SetProfilerManager(IProfilerManager*); +PSY_DRACO_API IDracoJobsController* GetJobsParallelController(); +PSY_DRACO_API void SetJobsParallelController(IDracoJobsController*); + namespace draco { @@ -57,7 +73,10 @@ enum PSY_DRACO_API MeshType : uint8_t * - 1.0: support incremental mesh compression * - 1.1: 2018/01/05 (*) * + support vertex color compression - * - Support I frame index encoding as part of the header + * - ?.?: + * + support I frame index encoding as part of the header + * - 1.2: 2018/02/07 + * + support encode/decode attributes parallely */ #define PSY_DRACO_API_MAJOR_VERSION 1 #define PSY_DRACO_API_MINOR_VERSION 1 diff --git a/src/draco/psy/psy_draco_encoder.cpp b/src/draco/psy/psy_draco_encoder.cpp index bdc2fe13..d0813fce 100644 --- a/src/draco/psy/psy_draco_encoder.cpp +++ b/src/draco/psy/psy_draco_encoder.cpp @@ -27,6 +27,20 @@ void SetProfilerManager(IProfilerManager* pProp) } gmpProfilerManager = pProp; } // SetProfilerManager + +static IDracoJobsController* gmpJobsParallelController = nullptr; +IDracoJobsController* GetJobsParallelController() +{ + return gmpJobsParallelController; +} // GetJobsParallelController +void SetJobsParallelController(IDracoJobsController* pProp) +{ + if (gmpJobsParallelController) + { + delete gmpJobsParallelController; + } + gmpJobsParallelController = pProp; +} // SetJobsParallelController } // namespace psy namespace psy