Chromium Code Reviews| Index: gpu/perftests/texture_upload_perftest.cc |
| diff --git a/gpu/perftests/texture_upload_perftest.cc b/gpu/perftests/texture_upload_perftest.cc |
| index add6343e2aa57213fe583b3d5a2a249671b53573..4b82d7dfbb511101a6c0f10124affe96b24bea28 100644 |
| --- a/gpu/perftests/texture_upload_perftest.cc |
| +++ b/gpu/perftests/texture_upload_perftest.cc |
| @@ -20,14 +20,15 @@ |
| #include "ui/gl/gl_context.h" |
| #include "ui/gl/gl_enums.h" |
| #include "ui/gl/gl_surface.h" |
| +#include "ui/gl/gl_version_info.h" |
| #include "ui/gl/gpu_timing.h" |
| #include "ui/gl/scoped_make_current.h" |
| namespace gpu { |
| namespace { |
| -const int kUploadPerfWarmupRuns = 10; |
| -const int kUploadPerfTestRuns = 100; |
| +const int kUploadPerfWarmupRuns = 5; |
| +const int kUploadPerfTestRuns = 30; |
| #define SHADER(Src) #Src |
| @@ -58,8 +59,8 @@ SHADER( |
| ); |
| // clang-format on |
| -void CheckNoGlError() { |
| - CHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| +void CheckNoGlError(const std::string& msg) { |
| + CHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()) << " " << msg; |
| } |
| // Utility function to compile a shader from a string. |
| @@ -90,6 +91,20 @@ int GLFormatBytePerPixel(GLenum format) { |
| return format == GL_RGBA ? 4 : 1; |
| } |
| +GLenum GLFormatToStorageFormat(GLenum format) { |
| + switch (format) { |
| + case GL_RGBA: |
| + return GL_RGBA8; |
| + case GL_LUMINANCE: |
| + return GL_LUMINANCE8; |
| + case GL_RED_EXT: |
| + return GL_R8; |
| + default: |
| + NOTREACHED(); |
| + } |
| + return 0; |
| +} |
| + |
| void GenerateTextureData(const gfx::Size& size, |
| int bytes_per_pixel, |
| const int seed, |
| @@ -227,7 +242,7 @@ class TextureUploadPerfTest : public testing::Test { |
| reinterpret_cast<void*>(sizeof(GLfloat) * 2)); |
| glEnableVertexAttribArray(0); |
| glEnableVertexAttribArray(1); |
| - CheckNoGlError(); |
| + CheckNoGlError("glEnableVertexAttribArray"); |
| } |
| void GenerateVertexBuffer(const gfx::Size& size) { |
| @@ -249,7 +264,7 @@ class TextureUploadPerfTest : public testing::Test { |
| right, top, 1.f, 1.f}; |
| // clang-format on |
| glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); |
| - CheckNoGlError(); |
| + CheckNoGlError("glBufferData"); |
| } |
| void TearDown() override { |
| @@ -262,7 +277,7 @@ class TextureUploadPerfTest : public testing::Test { |
| glBindFramebufferEXT(GL_FRAMEBUFFER, 0); |
| glDeleteFramebuffersEXT(1, &framebuffer_object_); |
| glDeleteTextures(1, &color_texture_); |
| - CheckNoGlError(); |
| + CheckNoGlError("glDeleteTextures"); |
| gpu_timing_client_ = nullptr; |
| gl_context_ = nullptr; |
| @@ -281,14 +296,32 @@ class TextureUploadPerfTest : public testing::Test { |
| void UploadTexture(GLuint texture_id, |
| const gfx::Size& size, |
| const std::vector<uint8>& pixels, |
| - GLenum format) { |
| - glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, |
| - format, GL_UNSIGNED_BYTE, &pixels[0]); |
| + GLenum format, |
| + const bool subimage, |
| + const bool glstorage) { |
| + if (subimage) { |
| + if (glstorage) { |
| + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GLFormatToStorageFormat(format), |
|
reveman
2015/03/18 22:32:34
is this called for each upload? or just once follo
Daniele Castagna
2015/03/19 00:25:32
Called for each upload. We generate a texture for
reveman
2015/03/19 02:01:35
Reusing the same texture would match normal usage
Daniele Castagna
2015/03/19 03:34:01
Done.
|
| + size.width(), size.height()); |
| + CheckNoGlError("glTexStorage2DEXT"); |
| + } else { |
| + glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, |
| + format, GL_UNSIGNED_BYTE, nullptr); |
| + } |
| + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.width(), size.height(), |
| + format, GL_UNSIGNED_BYTE, &pixels[0]); |
| + CheckNoGlError("glTexSubImage2D"); |
| + } else { |
| + DCHECK(!glstorage); |
| + glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, |
| + format, GL_UNSIGNED_BYTE, &pixels[0]); |
| + CheckNoGlError("glTexImage2D"); |
| + } |
| + |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| - CheckNoGlError(); |
| } |
| // Upload and draw on the offscren surface. |
| @@ -296,10 +329,12 @@ class TextureUploadPerfTest : public testing::Test { |
| // time elapsed in milliseconds. |
| std::vector<Measurement> UploadAndDraw(const gfx::Size& size, |
| const std::vector<uint8>& pixels, |
| - const GLenum format) { |
| + const GLenum format, |
| + const bool subimage, |
| + const bool glstorage) { |
| GLuint texture_id = CreateGLTexture(); |
| MeasurementTimers tex_timers(gpu_timing_client_.get()); |
| - UploadTexture(texture_id, size, pixels, format); |
| + UploadTexture(texture_id, size, pixels, format, glstorage, subimage); |
| tex_timers.Record(); |
| MeasurementTimers draw_timers(gpu_timing_client_.get()); |
| @@ -309,7 +344,7 @@ class TextureUploadPerfTest : public testing::Test { |
| MeasurementTimers finish_timers(gpu_timing_client_.get()); |
| glFinish(); |
| - CheckNoGlError(); |
| + CheckNoGlError("glFinish"); |
| finish_timers.Record(); |
| glDeleteTextures(1, &texture_id); |
| @@ -317,7 +352,7 @@ class TextureUploadPerfTest : public testing::Test { |
| std::vector<uint8> pixels_rendered(size.GetArea() * 4); |
| glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_BYTE, |
| &pixels_rendered[0]); |
| - CheckNoGlError(); |
| + CheckNoGlError("glReadPixels"); |
| EXPECT_TRUE( |
| CompareBufferToRGBABuffer(format, size, pixels, pixels_rendered)) |
| << "Format is: " << gfx::GLEnums::GetStringEnum(format); |
| @@ -335,14 +370,16 @@ class TextureUploadPerfTest : public testing::Test { |
| } |
| void RunUploadAndDrawMultipleTimes(const gfx::Size& size, |
| - const GLenum format) { |
| + const GLenum format, |
| + const bool subimage, |
| + const bool glstorage) { |
| std::vector<uint8> pixels; |
| base::SmallMap<std::map<std::string, Measurement>> |
| aggregates; // indexed by name |
| int successful_runs = 0; |
| for (int i = 0; i < kUploadPerfWarmupRuns + kUploadPerfTestRuns; ++i) { |
| GenerateTextureData(size, GLFormatBytePerPixel(format), i + 1, &pixels); |
| - auto run = UploadAndDraw(size, pixels, format); |
| + auto run = UploadAndDraw(size, pixels, format, glstorage, subimage); |
| if (i < kUploadPerfWarmupRuns || !run.size()) { |
| continue; |
| } |
| @@ -355,6 +392,13 @@ class TextureUploadPerfTest : public testing::Test { |
| } |
| std::string graph_name = base::StringPrintf( |
| "%d_%s", size.width(), gfx::GLEnums::GetStringEnum(format).c_str()); |
| + if (subimage) { |
| + graph_name += "_sub"; |
| + if (glstorage) { |
| + graph_name += "_stor"; |
| + } |
| + } |
| + |
| if (successful_runs) { |
| for (const auto& entry : aggregates) { |
| const auto m = entry.second.Divide(successful_runs); |
| @@ -390,21 +434,36 @@ TEST_F(TextureUploadPerfTest, glTexImage2d) { |
| formats.push_back(GL_LUMINANCE); |
| ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); |
| - bool has_texture_rg = gl_context_->HasExtension("GL_EXT_texture_rg") || |
| - gl_context_->HasExtension("GL_ARB_texture_rg"); |
| + const bool has_texture_rg = gl_context_->HasExtension("GL_EXT_texture_rg") || |
| + gl_context_->HasExtension("GL_ARB_texture_rg"); |
| if (has_texture_rg) { |
| // Used as ResourceProvider::yuv_resource_format_ if |
| // {ARB,EXT}_texture_rg are available. |
| formats.push_back(GL_RED_EXT); |
| } |
| + |
| + bool has_texture_storage = |
| + gl_context_->GetVersionInfo()->is_es3 || |
| + gl_context_->HasExtension("GL_EXT_texture_storage") || |
| + gl_context_->HasExtension("GL_ARB_texture_storage"); |
| for (int side : sizes) { |
| ASSERT_GE(fbo_size_.width(), side); |
| ASSERT_GE(fbo_size_.height(), side); |
| gfx::Size size(side, side); |
| GenerateVertexBuffer(size); |
| for (GLenum format : formats) { |
| - RunUploadAndDrawMultipleTimes(size, format); |
| + RunUploadAndDrawMultipleTimes(size, format, |
| + true, // use glTexSubimage2D |
| + false); |
| + if (has_texture_storage) { |
| + RunUploadAndDrawMultipleTimes(size, format, |
| + true, // use glTexSubimage2D |
| + true); // use glTexStorage2D |
| + } |
| + RunUploadAndDrawMultipleTimes(size, format, |
| + false, // use glTexImage2D |
| + false); |
| } |
| } |
| } |
| @@ -438,7 +497,8 @@ TEST_F(TextureUploadPerfTest, renaming) { |
| MeasurementTimers upload_and_draw_timers(gpu_timing_client_.get()); |
| for (int i = 0; i < 4; ++i) { |
| - UploadTexture(texture_id, texture_size, pixels[i % 4], GL_RGBA); |
| + UploadTexture(texture_id, texture_size, pixels[i % 4], GL_RGBA, true, |
| + false); |
| DCHECK_NE(-1, translation_location_); |
| glUniform2f(translation_location_, positions[i % 4].x(), |
| positions[i % 4].y()); |
| @@ -452,7 +512,7 @@ TEST_F(TextureUploadPerfTest, renaming) { |
| upload_and_draw_timers.Record(); |
| MeasurementTimers finish_timers(gpu_timing_client_.get()); |
| glFinish(); |
| - CheckNoGlError(); |
| + CheckNoGlError("glFinish"); |
| finish_timers.Record(); |
| glDeleteTextures(1, &texture_id); |
| @@ -463,7 +523,7 @@ TEST_F(TextureUploadPerfTest, renaming) { |
| texture_size.height() * positions[i].y(), texture_size.width(), |
| texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, |
| &pixels_rendered[0]); |
| - CheckNoGlError(); |
| + CheckNoGlError("glReadPixels"); |
| ASSERT_EQ(pixels[i].size(), pixels_rendered.size()); |
| EXPECT_EQ(pixels[i], pixels_rendered); |
| } |