Commit 959ead4b authored by Adrienne Walker's avatar Adrienne Walker Committed by Commit Bot

oop : Only adjust serialization alignment when needed

Alignment code was showing up in paint op serialization perf, so this
patch makes alignment explicit instead of implicit.  Callers that
know that their writes are already aligned aren't forced into extra
work.

DrawRectOp serialization is 6.2x faster and deserialization is 2.2x faster.

Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel
Change-Id: I5678c0510c3200eff496c07a6fbb88e70054b27b
Reviewed-on: https://chromium-review.googlesource.com/798470
Commit-Queue: enne <enne@chromium.org>
Reviewed-by: default avatarvmpstr <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#520990}
parent c9709c48
...@@ -347,6 +347,7 @@ size_t DrawImageOp::Serialize(const PaintOp* base_op, ...@@ -347,6 +347,7 @@ size_t DrawImageOp::Serialize(const PaintOp* base_op,
serialized_flags = &op->flags; serialized_flags = &op->flags;
helper.Write(*serialized_flags); helper.Write(*serialized_flags);
helper.Write(op->image, options.image_provider); helper.Write(op->image, options.image_provider);
helper.AlignMemory(alignof(SkScalar));
helper.Write(op->left); helper.Write(op->left);
helper.Write(op->top); helper.Write(op->top);
return helper.size(); return helper.size();
...@@ -393,6 +394,7 @@ size_t DrawLineOp::Serialize(const PaintOp* base_op, ...@@ -393,6 +394,7 @@ size_t DrawLineOp::Serialize(const PaintOp* base_op,
if (!serialized_flags) if (!serialized_flags)
serialized_flags = &op->flags; serialized_flags = &op->flags;
helper.Write(*serialized_flags); helper.Write(*serialized_flags);
helper.AlignMemory(alignof(SkScalar));
helper.Write(op->x0); helper.Write(op->x0);
helper.Write(op->y0); helper.Write(op->y0);
helper.Write(op->x1); helper.Write(op->x1);
...@@ -476,6 +478,7 @@ size_t DrawTextBlobOp::Serialize(const PaintOp* base_op, ...@@ -476,6 +478,7 @@ size_t DrawTextBlobOp::Serialize(const PaintOp* base_op,
if (!serialized_flags) if (!serialized_flags)
serialized_flags = &op->flags; serialized_flags = &op->flags;
helper.Write(*serialized_flags); helper.Write(*serialized_flags);
helper.AlignMemory(alignof(SkScalar));
helper.Write(op->x); helper.Write(op->x);
helper.Write(op->y); helper.Write(op->y);
helper.Write(op->blob); helper.Write(op->blob);
...@@ -694,6 +697,7 @@ PaintOp* DrawImageOp::Deserialize(const volatile void* input, ...@@ -694,6 +697,7 @@ PaintOp* DrawImageOp::Deserialize(const volatile void* input,
PaintOpReader helper(input, input_size); PaintOpReader helper(input, input_size);
helper.Read(&op->flags); helper.Read(&op->flags);
helper.Read(&op->image); helper.Read(&op->image);
helper.AlignMemory(alignof(SkScalar));
helper.Read(&op->left); helper.Read(&op->left);
helper.Read(&op->top); helper.Read(&op->top);
if (!helper.valid() || !op->IsValid()) { if (!helper.valid() || !op->IsValid()) {
...@@ -755,6 +759,7 @@ PaintOp* DrawLineOp::Deserialize(const volatile void* input, ...@@ -755,6 +759,7 @@ PaintOp* DrawLineOp::Deserialize(const volatile void* input,
PaintOpReader helper(input, input_size); PaintOpReader helper(input, input_size);
helper.Read(&op->flags); helper.Read(&op->flags);
helper.AlignMemory(alignof(SkScalar));
helper.Read(&op->x0); helper.Read(&op->x0);
helper.Read(&op->y0); helper.Read(&op->y0);
helper.Read(&op->x1); helper.Read(&op->x1);
...@@ -863,6 +868,7 @@ PaintOp* DrawTextBlobOp::Deserialize(const volatile void* input, ...@@ -863,6 +868,7 @@ PaintOp* DrawTextBlobOp::Deserialize(const volatile void* input,
PaintOpReader helper(input, input_size); PaintOpReader helper(input, input_size);
helper.Read(&op->flags); helper.Read(&op->flags);
helper.AlignMemory(alignof(SkScalar));
helper.Read(&op->x); helper.Read(&op->x);
helper.Read(&op->y); helper.Read(&op->y);
helper.Read(&op->blob); helper.Read(&op->blob);
...@@ -1669,8 +1675,8 @@ size_t PaintOp::Serialize(void* memory, ...@@ -1669,8 +1675,8 @@ size_t PaintOp::Serialize(void* memory,
if (written < 4) if (written < 4)
return 0u; return 0u;
size_t aligned_written = size_t aligned_written = ((written + PaintOpBuffer::PaintOpAlign - 1) &
MathUtil::UncheckedRoundUp(written, PaintOpBuffer::PaintOpAlign); ~(PaintOpBuffer::PaintOpAlign - 1));
if (aligned_written >= kMaxSkip) if (aligned_written >= kMaxSkip)
return 0u; return 0u;
if (aligned_written > size) if (aligned_written > size)
......
...@@ -94,8 +94,6 @@ template <typename T> ...@@ -94,8 +94,6 @@ template <typename T>
void PaintOpReader::ReadSimple(T* val) { void PaintOpReader::ReadSimple(T* val) {
static_assert(base::is_trivially_copyable<T>::value, static_assert(base::is_trivially_copyable<T>::value,
"Not trivially copyable"); "Not trivially copyable");
if (!AlignMemory(alignof(T)))
SetInvalid();
if (remaining_bytes_ < sizeof(T)) if (remaining_bytes_ < sizeof(T))
SetInvalid(); SetInvalid();
if (!valid_) if (!valid_)
...@@ -117,8 +115,6 @@ void PaintOpReader::ReadFlattenable(sk_sp<T>* val) { ...@@ -117,8 +115,6 @@ void PaintOpReader::ReadFlattenable(sk_sp<T>* val) {
ReadSimple(&bytes); ReadSimple(&bytes);
if (remaining_bytes_ < bytes) if (remaining_bytes_ < bytes)
SetInvalid(); SetInvalid();
if (!SkIsAlign4(reinterpret_cast<uintptr_t>(memory_)))
SetInvalid();
if (!valid_) if (!valid_)
return; return;
if (bytes == 0) if (bytes == 0)
...@@ -127,6 +123,7 @@ void PaintOpReader::ReadFlattenable(sk_sp<T>* val) { ...@@ -127,6 +123,7 @@ void PaintOpReader::ReadFlattenable(sk_sp<T>* val) {
// This is assumed safe from TOCTOU violations as the flattenable // This is assumed safe from TOCTOU violations as the flattenable
// deserializing function uses an SkReadBuffer which reads each piece of // deserializing function uses an SkReadBuffer which reads each piece of
// memory once much like PaintOpReader does. // memory once much like PaintOpReader does.
DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(memory_)));
val->reset(static_cast<T*>(SkValidatingDeserializeFlattenable( val->reset(static_cast<T*>(SkValidatingDeserializeFlattenable(
const_cast<const char*>(memory_), bytes, T::GetFlattenableType()))); const_cast<const char*>(memory_), bytes, T::GetFlattenableType())));
if (!val) if (!val)
...@@ -232,8 +229,11 @@ void PaintOpReader::Read(PaintFlags* flags) { ...@@ -232,8 +229,11 @@ void PaintOpReader::Read(PaintFlags* flags) {
// Flattenables must be read at 4-byte boundary, which should be the case // Flattenables must be read at 4-byte boundary, which should be the case
// here. // here.
ReadFlattenable(&flags->path_effect_); ReadFlattenable(&flags->path_effect_);
AlignMemory(4);
ReadFlattenable(&flags->mask_filter_); ReadFlattenable(&flags->mask_filter_);
AlignMemory(4);
ReadFlattenable(&flags->color_filter_); ReadFlattenable(&flags->color_filter_);
AlignMemory(4);
ReadFlattenable(&flags->draw_looper_); ReadFlattenable(&flags->draw_looper_);
Read(&flags->shader_); Read(&flags->shader_);
...@@ -490,7 +490,7 @@ void PaintOpReader::Read(SkColorType* color_type) { ...@@ -490,7 +490,7 @@ void PaintOpReader::Read(SkColorType* color_type) {
*color_type = static_cast<SkColorType>(raw_color_type); *color_type = static_cast<SkColorType>(raw_color_type);
} }
bool PaintOpReader::AlignMemory(size_t alignment) { void PaintOpReader::AlignMemory(size_t alignment) {
// Due to the math below, alignment must be a power of two. // Due to the math below, alignment must be a power of two.
DCHECK_GT(alignment, 0u); DCHECK_GT(alignment, 0u);
DCHECK_EQ(alignment & (alignment - 1), 0u); DCHECK_EQ(alignment & (alignment - 1), 0u);
...@@ -502,11 +502,10 @@ bool PaintOpReader::AlignMemory(size_t alignment) { ...@@ -502,11 +502,10 @@ bool PaintOpReader::AlignMemory(size_t alignment) {
// however, since it can be slow. // however, since it can be slow.
size_t padding = ((memory + alignment - 1) & ~(alignment - 1)) - memory; size_t padding = ((memory + alignment - 1) & ~(alignment - 1)) - memory;
if (padding > remaining_bytes_) if (padding > remaining_bytes_)
return false; valid_ = false;
memory_ += padding; memory_ += padding;
remaining_bytes_ -= padding; remaining_bytes_ -= padding;
return true;
} }
inline void PaintOpReader::SetInvalid() { inline void PaintOpReader::SetInvalid() {
......
...@@ -82,6 +82,9 @@ class CC_PAINT_EXPORT PaintOpReader { ...@@ -82,6 +82,9 @@ class CC_PAINT_EXPORT PaintOpReader {
// would exceed the available budfer. // would exceed the available budfer.
const volatile void* ExtractReadableMemory(size_t bytes); const volatile void* ExtractReadableMemory(size_t bytes);
// Aligns the memory to the given alignment.
void AlignMemory(size_t alignment);
private: private:
template <typename T> template <typename T>
void ReadSimple(T* val); void ReadSimple(T* val);
...@@ -95,10 +98,6 @@ class CC_PAINT_EXPORT PaintOpReader { ...@@ -95,10 +98,6 @@ class CC_PAINT_EXPORT PaintOpReader {
void SetInvalid(); void SetInvalid();
// Attempts to align the memory to the given alignment. Returns false if there
// is unsufficient bytes remaining to do this padding.
bool AlignMemory(size_t alignment);
const volatile char* memory_ = nullptr; const volatile char* memory_ = nullptr;
size_t remaining_bytes_ = 0u; size_t remaining_bytes_ = 0u;
bool valid_ = true; bool valid_ = true;
......
...@@ -23,8 +23,6 @@ PaintOpWriter::~PaintOpWriter() = default; ...@@ -23,8 +23,6 @@ PaintOpWriter::~PaintOpWriter() = default;
template <typename T> template <typename T>
void PaintOpWriter::WriteSimple(const T& val) { void PaintOpWriter::WriteSimple(const T& val) {
static_assert(base::is_trivially_copyable<T>::value, ""); static_assert(base::is_trivially_copyable<T>::value, "");
if (!AlignMemory(alignof(T)))
valid_ = false;
if (remaining_bytes_ < sizeof(T)) if (remaining_bytes_ < sizeof(T))
valid_ = false; valid_ = false;
if (!valid_) if (!valid_)
...@@ -37,13 +35,14 @@ void PaintOpWriter::WriteSimple(const T& val) { ...@@ -37,13 +35,14 @@ void PaintOpWriter::WriteSimple(const T& val) {
} }
void PaintOpWriter::WriteFlattenable(const SkFlattenable* val) { void PaintOpWriter::WriteFlattenable(const SkFlattenable* val) {
DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(memory_)))
<< "Flattenable must start writing at 4 byte alignment.";
if (!val) { if (!val) {
WriteSize(static_cast<size_t>(0u)); WriteSize(static_cast<size_t>(0u));
return; return;
} }
DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(memory_)))
<< "Flattenable must start writing at 4 byte alignment.";
// TODO(enne): change skia API to make this a const parameter. // TODO(enne): change skia API to make this a const parameter.
sk_sp<SkData> data( sk_sp<SkData> data(
SkValidatingSerializeFlattenable(const_cast<SkFlattenable*>(val))); SkValidatingSerializeFlattenable(const_cast<SkFlattenable*>(val)));
...@@ -114,8 +113,11 @@ void PaintOpWriter::Write(const PaintFlags& flags) { ...@@ -114,8 +113,11 @@ void PaintOpWriter::Write(const PaintFlags& flags) {
// Flattenables must be written starting at a 4 byte boundary, which should be // Flattenables must be written starting at a 4 byte boundary, which should be
// the case here. // the case here.
WriteFlattenable(flags.path_effect_.get()); WriteFlattenable(flags.path_effect_.get());
AlignMemory(4);
WriteFlattenable(flags.mask_filter_.get()); WriteFlattenable(flags.mask_filter_.get());
AlignMemory(4);
WriteFlattenable(flags.color_filter_.get()); WriteFlattenable(flags.color_filter_.get());
AlignMemory(4);
WriteFlattenable(flags.draw_looper_.get()); WriteFlattenable(flags.draw_looper_.get());
Write(flags.shader_.get()); Write(flags.shader_.get());
...@@ -260,7 +262,7 @@ void PaintOpWriter::WriteArray(size_t count, const SkPoint* input) { ...@@ -260,7 +262,7 @@ void PaintOpWriter::WriteArray(size_t count, const SkPoint* input) {
WriteData(bytes, input); WriteData(bytes, input);
} }
bool PaintOpWriter::AlignMemory(size_t alignment) { void PaintOpWriter::AlignMemory(size_t alignment) {
// Due to the math below, alignment must be a power of two. // Due to the math below, alignment must be a power of two.
DCHECK_GT(alignment, 0u); DCHECK_GT(alignment, 0u);
DCHECK_EQ(alignment & (alignment - 1), 0u); DCHECK_EQ(alignment & (alignment - 1), 0u);
...@@ -272,11 +274,10 @@ bool PaintOpWriter::AlignMemory(size_t alignment) { ...@@ -272,11 +274,10 @@ bool PaintOpWriter::AlignMemory(size_t alignment) {
// however, since it can be slow. // however, since it can be slow.
size_t padding = ((memory + alignment - 1) & ~(alignment - 1)) - memory; size_t padding = ((memory + alignment - 1) & ~(alignment - 1)) - memory;
if (padding > remaining_bytes_) if (padding > remaining_bytes_)
return false; valid_ = false;
memory_ += padding; memory_ += padding;
remaining_bytes_ -= padding; remaining_bytes_ -= padding;
return true;
} }
} // namespace cc } // namespace cc
...@@ -61,6 +61,9 @@ class CC_PAINT_EXPORT PaintOpWriter { ...@@ -61,6 +61,9 @@ class CC_PAINT_EXPORT PaintOpWriter {
} }
void Write(bool data) { Write(static_cast<uint8_t>(data)); } void Write(bool data) { Write(static_cast<uint8_t>(data)); }
// Aligns the memory to the given alignment.
void AlignMemory(size_t alignment);
private: private:
template <typename T> template <typename T>
void WriteSimple(const T& val); void WriteSimple(const T& val);
...@@ -71,10 +74,6 @@ class CC_PAINT_EXPORT PaintOpWriter { ...@@ -71,10 +74,6 @@ class CC_PAINT_EXPORT PaintOpWriter {
static void TypefaceCataloger(SkTypeface* typeface, void* ctx); static void TypefaceCataloger(SkTypeface* typeface, void* ctx);
// Attempts to align the memory to the given alignment. Returns false if there
// is unsufficient bytes remaining to do this padding.
bool AlignMemory(size_t alignment);
char* memory_ = nullptr; char* memory_ = nullptr;
size_t size_ = 0u; size_t size_ = 0u;
size_t remaining_bytes_ = 0u; size_t remaining_bytes_ = 0u;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment