Commit 5f3849aa authored by radu.velea's avatar radu.velea Committed by Commit bot

Add ETC1 powered SSE encoder for tile texture compression

Created an ETC1 encoder that uses SSE2 to improve compression speed.
The SSE encoder extends TextureCompressor and uses the same algorithm as TextureCompressorETC1.

Added unittest for TextureCompressorETC1.

Moved shared code into a etc1 header.

Added new performance test scenarios.

Performance difference on Ubuntu x64, Haswell Processor:
Without SSE:
*RESULT Compress256x256BlackAndWhiteGradientImage: ETC1 Low= 1.966321587562561 us
*RESULT Compress256x256SolidBlackImage: ETC1 Low= .0956009104847908 us
*RESULT Compress256x256SolidColorImage: ETC1 Low= .4367307722568512 us
*RESULT Compress256x256RandomColorImage: ETC1 Low= 5.948055744171143 us

With SSE:
*RESULT Compress256x256BlackAndWhiteGradientImage: ETC1 Low= 1.0316201448440552 us
*RESULT Compress256x256SolidBlackImage: ETC1 Low= .25716209411621094 us
*RESULT Compress256x256SolidColorImage: ETC1 Low= .2768038809299469 us
*RESULT Compress256x256RandomColorImage: ETC1 Low= 1.834145426750183 us

BUG=434699
TEST=newly added unittest TextureCompressorETC1Test::Compress256x256CreateETC1, TextureCompressorETC1Test::Compress256x256RatioETC1

Review URL: https://codereview.chromium.org/1096703002

Cr-Commit-Position: refs/heads/master@{#329840}
parent 557da2ea
......@@ -421,6 +421,7 @@ Qiankun Miao <qiankun.miao@intel.com>
Qing Zhang <qing.zhang@intel.com>
Qi Yang <qi1988.yang@samsung.com>
Radu Stavila <stavila@adobe.com>
Radu Velea <radu.velea@intel.com>
Rafael Antognolli <rafael.antognolli@intel.com>
Raghavendra Ghatage <r.ghatage@samsung.com>
Rahul Gupta <rahul.g@samsung.com>
......
......@@ -540,6 +540,7 @@ component("cc") {
deps = [
"//base",
"//base/third_party/dynamic_annotations",
"//cc:cc_opts",
"//cc/surfaces:surface_id",
"//gpu",
"//gpu/command_buffer/client:gles2_interface",
......@@ -557,6 +558,36 @@ component("cc") {
}
}
source_set("cc_opts") {
public_deps = [
"//cc:cc_opts_sse",
]
}
source_set("cc_opts_sse") {
if (target_cpu == "ia32" || target_cpu == "x64") {
deps = [
"//base",
]
defines = [ "CC_IMPLEMENTATION=1" ]
if (!is_debug && (is_win || is_android)) {
configs -= [ "//build/config/compiler:optimize" ]
configs += [ "//build/config/compiler:optimize_max" ]
}
sources = [
"resources/texture_compressor.h",
"resources/texture_compressor_etc1.h",
"resources/texture_compressor_etc1_sse.cc",
"resources/texture_compressor_etc1_sse.h",
]
cflags = [ "-msse2" ]
}
}
source_set("test_support") {
testonly = true
sources = [
......@@ -811,6 +842,7 @@ test("cc_unittests") {
"resources/scoped_gpu_raster_unittest.cc",
"resources/scoped_resource_unittest.cc",
"resources/task_graph_runner_unittest.cc",
"resources/texture_compressor_etc1_unittest.cc",
"resources/texture_mailbox_deleter_unittest.cc",
"resources/texture_uploader_unittest.cc",
"resources/tile_manager_unittest.cc",
......
......@@ -20,6 +20,7 @@
'<(DEPTH)/ui/events/events.gyp:events_base',
'<(DEPTH)/ui/gfx/gfx.gyp:gfx',
'<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry',
'cc_opts',
],
'variables': {
'optimize': 'max',
......@@ -632,5 +633,41 @@
'../build/android/increase_size_for_speed.gypi',
],
},
{
'target_name': 'cc_opts',
'type': 'static_library',
'conditions': [
['target_arch == "ia32" or target_arch == "x64"', {
'defines': [
'CC_IMPLEMENTATION=1',
],
'dependencies': [
'cc_opts_sse',
]
}],
],
},
{
'target_name': 'cc_opts_sse',
'type': 'static_library',
'dependencies': [
'<(DEPTH)/base/base.gyp:base',
],
'conditions': [
['target_arch == "ia32" or target_arch == "x64"', {
'defines': [
'CC_IMPLEMENTATION=1',
],
'sources': [
# Conditional compilation for SSE2 code on x86 and x64 machines
'resources/texture_compressor_etc1_sse.cc',
'resources/texture_compressor_etc1_sse.h',
],
'cflags': [
'-msse2',
],
}],
],
},
],
}
......@@ -93,6 +93,7 @@
'resources/scoped_gpu_raster_unittest.cc',
'resources/scoped_resource_unittest.cc',
'resources/task_graph_runner_unittest.cc',
'resources/texture_compressor_etc1_unittest.cc',
'resources/texture_mailbox_deleter_unittest.cc',
'resources/texture_uploader_unittest.cc',
'resources/tile_manager_unittest.cc',
......
......@@ -7,13 +7,25 @@
#include "base/logging.h"
#include "cc/resources/texture_compressor_etc1.h"
#if defined(ARCH_CPU_X86_FAMILY)
#include "base/cpu.h"
#include "cc/resources/texture_compressor_etc1_sse.h"
#endif
namespace cc {
scoped_ptr<TextureCompressor> TextureCompressor::Create(Format format) {
switch (format) {
case kFormatETC1:
case kFormatETC1: {
#if defined(ARCH_CPU_X86_FAMILY)
base::CPU cpu;
if (cpu.has_sse2()) {
return make_scoped_ptr(new TextureCompressorETC1SSE());
}
#endif
return make_scoped_ptr(new TextureCompressorETC1());
}
}
NOTREACHED();
return nullptr;
......
......@@ -18,180 +18,11 @@
// performance hit.
// #define USE_PERCEIVED_ERROR_METRIC
namespace {
template <typename T>
inline T clamp(T val, T min, T max) {
return val < min ? min : (val > max ? max : val);
}
inline uint8_t round_to_5_bits(float val) {
return clamp<uint8_t>(val * 31.0f / 255.0f + 0.5f, 0, 31);
}
inline uint8_t round_to_4_bits(float val) {
return clamp<uint8_t>(val * 15.0f / 255.0f + 0.5f, 0, 15);
}
union Color {
struct BgraColorType {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} channels;
uint8_t components[4];
uint32_t bits;
};
/*
* Codeword tables.
* See: Table 3.17.2
*/
static const int16_t g_codeword_tables[8][4] = {{-8, -2, 2, 8},
{-17, -5, 5, 17},
{-29, -9, 9, 29},
{-42, -13, 13, 42},
{-60, -18, 18, 60},
{-80, -24, 24, 80},
{-106, -33, 33, 106},
{-183, -47, 47, 183}};
/*
* Maps modifier indices to pixel index values.
* See: Table 3.17.3
*/
static const uint8_t g_mod_to_pix[4] = {3, 2, 0, 1};
/*
* The ETC1 specification index texels as follows:
*
* [a][e][i][m] [ 0][ 4][ 8][12]
* [b][f][j][n] <-> [ 1][ 5][ 9][13]
* [c][g][k][o] [ 2][ 6][10][14]
* [d][h][l][p] [ 3][ 7][11][15]
*
* However, when extracting sub blocks from BGRA data the natural array
* indexing order ends up different:
*
* vertical0: [a][e][b][f] horizontal0: [a][e][i][m]
* [c][g][d][h] [b][f][j][n]
* vertical1: [i][m][j][n] horizontal1: [c][g][k][o]
* [k][o][l][p] [d][h][l][p]
*
* In order to translate from the natural array indices in a sub block to the
* indices (number) used by specification and hardware we use this table.
*/
static const uint8_t g_idx_to_num[4][8] = {
{0, 4, 1, 5, 2, 6, 3, 7}, // Vertical block 0.
{8, 12, 9, 13, 10, 14, 11, 15}, // Vertical block 1.
{0, 4, 8, 12, 1, 5, 9, 13}, // Horizontal block 0.
{2, 6, 10, 14, 3, 7, 11, 15} // Horizontal block 1.
};
inline void WriteColors444(uint8_t* block,
const Color& color0,
const Color& color1) {
block[0] = (color0.channels.r & 0xf0) | (color1.channels.r >> 4);
block[1] = (color0.channels.g & 0xf0) | (color1.channels.g >> 4);
block[2] = (color0.channels.b & 0xf0) | (color1.channels.b >> 4);
}
inline void WriteColors555(uint8_t* block,
const Color& color0,
const Color& color1) {
// Table for conversion to 3-bit two complement format.
static const uint8_t two_compl_trans_table[8] = {
4, // -4 (100b)
5, // -3 (101b)
6, // -2 (110b)
7, // -1 (111b)
0, // 0 (000b)
1, // 1 (001b)
2, // 2 (010b)
3, // 3 (011b)
};
int16_t delta_r =
static_cast<int16_t>(color1.channels.r >> 3) - (color0.channels.r >> 3);
int16_t delta_g =
static_cast<int16_t>(color1.channels.g >> 3) - (color0.channels.g >> 3);
int16_t delta_b =
static_cast<int16_t>(color1.channels.b >> 3) - (color0.channels.b >> 3);
DCHECK(delta_r >= -4 && delta_r <= 3);
DCHECK(delta_g >= -4 && delta_g <= 3);
DCHECK(delta_b >= -4 && delta_b <= 3);
block[0] = (color0.channels.r & 0xf8) | two_compl_trans_table[delta_r + 4];
block[1] = (color0.channels.g & 0xf8) | two_compl_trans_table[delta_g + 4];
block[2] = (color0.channels.b & 0xf8) | two_compl_trans_table[delta_b + 4];
}
inline void WriteCodewordTable(uint8_t* block,
uint8_t sub_block_id,
uint8_t table) {
DCHECK_LT(sub_block_id, 2);
DCHECK_LT(table, 8);
uint8_t shift = (2 + (3 - sub_block_id * 3));
block[3] &= ~(0x07 << shift);
block[3] |= table << shift;
}
inline void WritePixelData(uint8_t* block, uint32_t pixel_data) {
block[4] |= pixel_data >> 24;
block[5] |= (pixel_data >> 16) & 0xff;
block[6] |= (pixel_data >> 8) & 0xff;
block[7] |= pixel_data & 0xff;
}
inline void WriteFlip(uint8_t* block, bool flip) {
block[3] &= ~0x01;
block[3] |= static_cast<uint8_t>(flip);
}
inline void WriteDiff(uint8_t* block, bool diff) {
block[3] &= ~0x02;
block[3] |= static_cast<uint8_t>(diff) << 1;
}
/**
* Compress and rounds BGR888 into BGR444. The resulting BGR444 color is
* expanded to BGR888 as it would be in hardware after decompression. The
* actual 444-bit data is available in the four most significant bits of each
* channel.
*/
inline Color MakeColor444(const float* bgr) {
uint8_t b4 = round_to_4_bits(bgr[0]);
uint8_t g4 = round_to_4_bits(bgr[1]);
uint8_t r4 = round_to_4_bits(bgr[2]);
Color bgr444;
bgr444.channels.b = (b4 << 4) | b4;
bgr444.channels.g = (g4 << 4) | g4;
bgr444.channels.r = (r4 << 4) | r4;
return bgr444;
}
namespace cc {
/**
* Compress and rounds BGR888 into BGR555. The resulting BGR555 color is
* expanded to BGR888 as it would be in hardware after decompression. The
* actual 555-bit data is available in the five most significant bits of each
* channel.
*/
inline Color MakeColor555(const float* bgr) {
uint8_t b5 = round_to_5_bits(bgr[0]);
uint8_t g5 = round_to_5_bits(bgr[1]);
uint8_t r5 = round_to_5_bits(bgr[2]);
Color bgr555;
bgr555.channels.b = (b5 << 3) | (b5 >> 2);
bgr555.channels.g = (g5 << 3) | (g5 >> 2);
bgr555.channels.r = (r5 << 3) | (r5 >> 2);
return bgr555;
}
namespace {
/**
* Constructs a color from a given base color and luminance value.
*/
// Constructs a color from a given base color and luminance value.
inline Color MakeColor(const Color& base, int16_t lum) {
int b = static_cast<int>(base.channels.b) + lum;
int g = static_cast<int>(base.channels.g) + lum;
......@@ -203,10 +34,8 @@ inline Color MakeColor(const Color& base, int16_t lum) {
return color;
}
/**
* Calculates the error metric for two colors. A small error signals that the
* colors are similar to each other, a large error the signals the opposite.
*/
// Calculates the error metric for two colors. A small error signals that the
// colors are similar to each other, a large error the signals the opposite.
inline uint32_t GetColorError(const Color& u, const Color& v) {
#ifdef USE_PERCEIVED_ERROR_METRIC
float delta_b = static_cast<float>(u.channels.b) - v.channels.b;
......@@ -461,15 +290,15 @@ void CompressBlock(uint8_t* dst, const Color* ver_src, const Color* hor_src) {
} // namespace
namespace cc {
void TextureCompressorETC1::Compress(const uint8_t* src,
uint8_t* dst,
int width,
int height,
Quality quality) {
DCHECK(width >= 4 && (width & 3) == 0);
DCHECK(height >= 4 && (height & 3) == 0);
DCHECK_GE(width, 4);
DCHECK_EQ((width & 3), 0);
DCHECK_GE(height, 4);
DCHECK_EQ((height & 3), 0);
Color ver_blocks[16];
Color hor_blocks[16];
......
......@@ -7,8 +7,183 @@
#include "cc/resources/texture_compressor.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
namespace cc {
template <typename T>
inline T clamp(T val, T min, T max) {
return val < min ? min : (val > max ? max : val);
}
inline uint8_t round_to_5_bits(float val) {
return clamp<uint8_t>(val * 31.0f / 255.0f + 0.5f, 0, 31);
}
inline uint8_t round_to_4_bits(float val) {
return clamp<uint8_t>(val * 15.0f / 255.0f + 0.5f, 0, 15);
}
union Color {
struct BgraColorType {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} channels;
uint8_t components[4];
uint32_t bits;
};
// Codeword tables.
// See: Table 3.17.2
ALIGNAS(16) static const int16_t g_codeword_tables[8][4] = {
{-8, -2, 2, 8},
{-17, -5, 5, 17},
{-29, -9, 9, 29},
{-42, -13, 13, 42},
{-60, -18, 18, 60},
{-80, -24, 24, 80},
{-106, -33, 33, 106},
{-183, -47, 47, 183}};
// Maps modifier indices to pixel index values.
// See: Table 3.17.3
static const uint8_t g_mod_to_pix[4] = {3, 2, 0, 1};
// The ETC1 specification index texels as follows:
// [a][e][i][m] [ 0][ 4][ 8][12]
// [b][f][j][n] <-> [ 1][ 5][ 9][13]
// [c][g][k][o] [ 2][ 6][10][14]
// [d][h][l][p] [ 3][ 7][11][15]
// [ 0][ 1][ 2][ 3] [ 0][ 1][ 4][ 5]
// [ 4][ 5][ 6][ 7] <-> [ 8][ 9][12][13]
// [ 8][ 9][10][11] [ 2][ 3][ 6][ 7]
// [12][13][14][15] [10][11][14][15]
// However, when extracting sub blocks from BGRA data the natural array
// indexing order ends up different:
// vertical0: [a][e][b][f] horizontal0: [a][e][i][m]
// [c][g][d][h] [b][f][j][n]
// vertical1: [i][m][j][n] horizontal1: [c][g][k][o]
// [k][o][l][p] [d][h][l][p]
// In order to translate from the natural array indices in a sub block to the
// indices (number) used by specification and hardware we use this table.
static const uint8_t g_idx_to_num[4][8] = {
{0, 4, 1, 5, 2, 6, 3, 7}, // Vertical block 0.
{8, 12, 9, 13, 10, 14, 11, 15}, // Vertical block 1.
{0, 4, 8, 12, 1, 5, 9, 13}, // Horizontal block 0.
{2, 6, 10, 14, 3, 7, 11, 15} // Horizontal block 1.
};
inline void WriteColors444(uint8_t* block,
const Color& color0,
const Color& color1) {
// Write output color for BGRA textures.
block[0] = (color0.channels.r & 0xf0) | (color1.channels.r >> 4);
block[1] = (color0.channels.g & 0xf0) | (color1.channels.g >> 4);
block[2] = (color0.channels.b & 0xf0) | (color1.channels.b >> 4);
}
inline void WriteColors555(uint8_t* block,
const Color& color0,
const Color& color1) {
// Table for conversion to 3-bit two complement format.
static const uint8_t two_compl_trans_table[8] = {
4, // -4 (100b)
5, // -3 (101b)
6, // -2 (110b)
7, // -1 (111b)
0, // 0 (000b)
1, // 1 (001b)
2, // 2 (010b)
3, // 3 (011b)
};
int16_t delta_r =
static_cast<int16_t>(color1.channels.r >> 3) - (color0.channels.r >> 3);
int16_t delta_g =
static_cast<int16_t>(color1.channels.g >> 3) - (color0.channels.g >> 3);
int16_t delta_b =
static_cast<int16_t>(color1.channels.b >> 3) - (color0.channels.b >> 3);
DCHECK_GE(delta_r, -4);
DCHECK_LE(delta_r, 3);
DCHECK_GE(delta_g, -4);
DCHECK_LE(delta_g, 3);
DCHECK_GE(delta_b, -4);
DCHECK_LE(delta_b, 3);
// Write output color for BGRA textures.
block[0] = (color0.channels.r & 0xf8) | two_compl_trans_table[delta_r + 4];
block[1] = (color0.channels.g & 0xf8) | two_compl_trans_table[delta_g + 4];
block[2] = (color0.channels.b & 0xf8) | two_compl_trans_table[delta_b + 4];
}
inline void WriteCodewordTable(uint8_t* block,
uint8_t sub_block_id,
uint8_t table) {
DCHECK_LT(sub_block_id, 2);
DCHECK_LT(table, 8);
uint8_t shift = (2 + (3 - sub_block_id * 3));
block[3] &= ~(0x07 << shift);
block[3] |= table << shift;
}
inline void WritePixelData(uint8_t* block, uint32_t pixel_data) {
block[4] |= pixel_data >> 24;
block[5] |= (pixel_data >> 16) & 0xff;
block[6] |= (pixel_data >> 8) & 0xff;
block[7] |= pixel_data & 0xff;
}
inline void WriteFlip(uint8_t* block, bool flip) {
block[3] &= ~0x01;
block[3] |= static_cast<uint8_t>(flip);
}
inline void WriteDiff(uint8_t* block, bool diff) {
block[3] &= ~0x02;
block[3] |= static_cast<uint8_t>(diff) << 1;
}
// Compress and rounds BGR888 into BGR444. The resulting BGR444 color is
// expanded to BGR888 as it would be in hardware after decompression. The
// actual 444-bit data is available in the four most significant bits of each
// channel.
inline Color MakeColor444(const float* bgr) {
uint8_t b4 = round_to_4_bits(bgr[0]);
uint8_t g4 = round_to_4_bits(bgr[1]);
uint8_t r4 = round_to_4_bits(bgr[2]);
Color bgr444;
bgr444.channels.b = (b4 << 4) | b4;
bgr444.channels.g = (g4 << 4) | g4;
bgr444.channels.r = (r4 << 4) | r4;
// Added to distinguish between expanded 555 and 444 colors.
bgr444.channels.a = 0x44;
return bgr444;
}
// Compress and rounds BGR888 into BGR555. The resulting BGR555 color is
// expanded to BGR888 as it would be in hardware after decompression. The
// actual 555-bit data is available in the five most significant bits of each
// channel.
inline Color MakeColor555(const float* bgr) {
uint8_t b5 = round_to_5_bits(bgr[0]);
uint8_t g5 = round_to_5_bits(bgr[1]);
uint8_t r5 = round_to_5_bits(bgr[2]);
Color bgr555;
bgr555.channels.b = (b5 << 3) | (b5 >> 2);
bgr555.channels.g = (g5 << 3) | (g5 >> 2);
bgr555.channels.r = (r5 << 3) | (r5 >> 2);
// Added to distinguish between expanded 555 and 444 colors.
bgr555.channels.a = 0x55;
return bgr555;
}
class CC_EXPORT TextureCompressorETC1 : public TextureCompressor {
public:
TextureCompressorETC1() {}
......
This diff is collapsed.
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_RESOURCES_TEXTURE_COMPRESSOR_ETC1_SSE_H_
#define CC_RESOURCES_TEXTURE_COMPRESSOR_ETC1_SSE_H_
#include "cc/resources/texture_compressor.h"
namespace cc {
class CC_EXPORT TextureCompressorETC1SSE : public TextureCompressor {
public:
TextureCompressorETC1SSE() {}
// Compress a texture using ETC1. Note that the |quality| parameter is
// ignored. The current implementation does not support different quality
// settings.
void Compress(const uint8_t* src,
uint8_t* dst,
int width,
int height,
Quality quality) override;
private:
DISALLOW_COPY_AND_ASSIGN(TextureCompressorETC1SSE);
};
} // namespace cc
#endif // CC_RESOURCES_TEXTURE_COMPRESSOR_ETC1_SSE_H_
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/resources/texture_compressor.h"
#include "cc/base/util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
namespace {
const int kImageWidth = 256;
const int kImageHeight = 256;
const int kImageChannels = 4;
const int kImageSizeInBytes = kImageWidth * kImageHeight * kImageChannels;
TEST(TextureCompressorETC1Test, Compress256x256Ratio) {
scoped_ptr<TextureCompressor> compressor =
TextureCompressor::Create(TextureCompressor::kFormatETC1);
uint8_t src[kImageSizeInBytes];
uint8_t dst[kImageSizeInBytes];
const unsigned int kImagePoison = 0xDEADBEEF;
// Poison destination bytes so we can see how much has been
// overwritten by compression algorithm.
uint32_t* dst_32 = reinterpret_cast<uint32_t*>(dst);
for (int i = 0; i < kImageWidth * kImageHeight; i++) {
dst_32[i] = kImagePoison;
}
// Generate test texture.
for (int i = 0; i < kImageSizeInBytes; i++) {
src[i] = i % 256;
}
compressor->Compress(src, dst, kImageWidth, kImageHeight,
TextureCompressor::kQualityLow);
int compressed_size = 0;
for (compressed_size = 0; compressed_size < kImageWidth * kImageHeight;
compressed_size++) {
if (dst_32[compressed_size] == kImagePoison) {
// Represents size in bytes of the compressed block.
compressed_size = compressed_size * 4;
break;
}
}
// Check if compression ratio is 8:1 for RGBA or BGRA images, after discarding
// alpha channel.
EXPECT_EQ(kImageSizeInBytes, compressed_size * 8);
}
} // namespace
} // namespace cc
......@@ -17,12 +17,8 @@ const int kTimeCheckInterval = 10;
const int kImageWidth = 256;
const int kImageHeight = 256;
const int kImageSizeInBytes = kImageWidth * kImageHeight * 4;
const TextureCompressor::Quality kQualities[] = {
TextureCompressor::kQualityLow,
TextureCompressor::kQualityMedium,
TextureCompressor::kQualityHigh};
const int kImageChannels = 4;
const int kImageSizeInBytes = kImageWidth * kImageHeight * kImageChannels;
std::string FormatName(TextureCompressor::Format format) {
switch (format) {
......@@ -49,7 +45,9 @@ std::string QualityName(TextureCompressor::Quality quality) {
}
class TextureCompressorPerfTest
: public testing::TestWithParam<TextureCompressor::Format> {
: public testing::TestWithParam<
::testing::tuple<TextureCompressor::Quality,
TextureCompressor::Format>> {
public:
TextureCompressorPerfTest()
: timer_(kWarmupRuns,
......@@ -57,18 +55,20 @@ class TextureCompressorPerfTest
kTimeCheckInterval) {}
void SetUp() override {
TextureCompressor::Format format = GetParam();
TextureCompressor::Format format = ::testing::get<1>(GetParam());
compressor_ = TextureCompressor::Create(format);
}
void RunTest(const std::string& name, TextureCompressor::Quality quality) {
void RunTest(const std::string& name) {
TextureCompressor::Quality quality = ::testing::get<0>(GetParam());
timer_.Reset();
do {
compressor_->Compress(src_, dst_, kImageWidth, kImageHeight, quality);
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
std::string str = FormatName(GetParam()) + " " + QualityName(quality);
TextureCompressor::Format format = ::testing::get<1>(GetParam());
std::string str = FormatName(format) + " " + QualityName(quality);
perf_test::PrintResult("Compress256x256", name, str, timer_.MsPerLap(),
"us", true);
}
......@@ -80,24 +80,42 @@ class TextureCompressorPerfTest
uint8_t dst_[kImageSizeInBytes];
};
TEST_P(TextureCompressorPerfTest, Compress256x256Image) {
TEST_P(TextureCompressorPerfTest, Compress256x256BlackAndWhiteGradientImage) {
for (int i = 0; i < kImageSizeInBytes; ++i)
src_[i] = i % 256;
for (auto& quality : kQualities)
RunTest("Image", quality);
RunTest("BlackAndWhiteGradientImage");
}
TEST_P(TextureCompressorPerfTest, Compress256x256SolidImage) {
TEST_P(TextureCompressorPerfTest, Compress256x256SolidBlackImage) {
memset(src_, 0, kImageSizeInBytes);
for (auto& quality : kQualities)
RunTest("SolidImage", quality);
RunTest("SolidBlackImage");
}
TEST_P(TextureCompressorPerfTest, Compress256x256SolidColorImage) {
for (int i = 0; i < kImageSizeInBytes; ++i)
src_[i] = (4 - i % 4) * 50;
RunTest("SolidColorImage");
}
INSTANTIATE_TEST_CASE_P(TextureCompressorPerfTests,
TEST_P(TextureCompressorPerfTest, Compress256x256RandomColorImage) {
unsigned int kImageSeed = 1234567890;
srand(kImageSeed);
for (int i = 0; i < kImageSizeInBytes; ++i)
src_[i] = rand() % 256; // NOLINT
RunTest("RandomColorImage");
}
INSTANTIATE_TEST_CASE_P(
TextureCompressorPerfTests,
TextureCompressorPerfTest,
::testing::Values(TextureCompressor::kFormatETC1));
::testing::Combine(::testing::Values(TextureCompressor::kQualityLow,
TextureCompressor::kQualityMedium,
TextureCompressor::kQualityHigh),
::testing::Values(TextureCompressor::kFormatETC1)));
} // namespace
} // namespace cc
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