Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Unified Diff: gpu/command_buffer/service/texture_manager.cc

Issue 633773002: Optimized Texture::Update() function. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: gpu/command_buffer/service/texture_manager.cc
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index acc63d779c8f0ee8bf5868015d09ddbb2ee5a416..08fe659d6fa4cbf1e92aa87f1f3de53b2c012c7a 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -128,6 +128,9 @@ Texture::Texture(GLuint service_id)
service_id_(service_id),
cleared_(true),
num_uncleared_mips_(0),
+ num_npot_faces_(0),
+ num_complete_faces_(0),
+ num_incomplete_mips_(0),
target_(0),
min_filter_(GL_NEAREST_MIPMAP_LINEAR),
mag_filter_(GL_LINEAR),
@@ -329,8 +332,8 @@ bool Texture::MarkMipmapsGenerated(
GLsizei depth = info1.depth;
GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D :
GLES2Util::IndexToGLFaceTarget(ii);
- int num_mips =
- TextureManager::ComputeMipMapCount(target_, width, height, depth);
+
+ const int num_mips = num_mip_levels_[ii];
for (int level = 1; level < num_mips; ++level) {
width = std::max(1, width >> 1);
height = std::max(1, height >> 1);
@@ -361,6 +364,7 @@ void Texture::SetTarget(
for (size_t ii = 0; ii < num_faces; ++ii) {
level_infos_[ii].resize(max_levels);
}
+ num_mip_levels_.resize(num_faces);
if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) {
min_filter_ = GL_LINEAR;
@@ -407,6 +411,59 @@ bool Texture::CanGenerateMipmaps(
return true;
}
+bool Texture::TextureIsNPOT(GLsizei width,
+ GLsizei height,
+ GLsizei depth) {
+ return (GLES2Util::IsNPOT(width) ||
+ GLES2Util::IsNPOT(height) ||
+ GLES2Util::IsNPOT(depth));
+}
+
+bool Texture::TextureFaceComplete(const Texture::LevelInfo& first_face,
+ size_t face_index,
+ GLenum target,
+ GLenum internal_format,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type) {
+ bool complete = (target != 0 && depth == 1);
+ if (face_index != 0) {
+ complete &= (width == first_face.width &&
+ height == first_face.height &&
+ internal_format == first_face.internal_format &&
+ format == first_face.format &&
+ type == first_face.type);
+ }
+ return complete;
+}
+
+bool Texture::TextureMipComplete(const Texture::LevelInfo& level0_face,
+ GLenum target,
+ GLint level,
+ GLenum internal_format,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type) {
+ bool complete = (target != 0);
+ if (level != 0) {
+ const GLsizei mip_width = std::max(1, level0_face.width >> level);
+ const GLsizei mip_height = std::max(1, level0_face.height >> level);
+ const GLsizei mip_depth = std::max(1, level0_face.depth >> level);
vmiura 2014/10/07 00:13:03 Do we need to handle the case of width/height/dept
David Yen 2014/10/09 20:20:16 That check is already done before this function is
+
+ complete &= (width == mip_width &&
+ height == mip_height &&
+ depth == mip_depth &&
+ internal_format == level0_face.internal_format &&
+ format == level0_face.format &&
+ type == level0_face.type);
+ }
+ return complete;
+}
+
void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) {
DCHECK_GE(level, 0);
size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
@@ -516,6 +573,89 @@ void Texture::SetLevelInfo(
DCHECK_GE(depth, 0);
Texture::LevelInfo& info =
level_infos_[face_index][level];
+
+ // Update counters only if any attributes have changed. Counters are
+ // comparisons between the old and new values so it must be done before any
+ // assignment has been done to the LevelInfo.
+ if (info.target != target ||
+ info.internal_format != internal_format ||
+ info.width != width ||
+ info.height != height ||
+ info.depth != depth ||
+ info.format != format ||
+ info.type != type) {
+ if (level == 0) {
+ // Calculate the mip level count.
+ num_mip_levels_[face_index] = TextureManager::ComputeMipMapCount(
+ target_, width, height, depth);
+
+ // Update NPOT face count for the first level.
+ bool prev_npot = TextureIsNPOT(info.width, info.height, info.depth);
+ bool now_npot = TextureIsNPOT(width, height, depth);
+ if (prev_npot != now_npot)
+ num_npot_faces_ += now_npot ? 1 : -1;
+
+ // Update number of complete faces.
+ const Texture::LevelInfo& first_face = level_infos_[0][0];
+ for (size_t i = face_index; i < level_infos_.size(); ++i) {
vmiura 2014/10/07 00:13:03 I think this compares face 0 to itself, so I think
David Yen 2014/10/09 20:20:16 No longer relevant, using dirty bit now.
+ bool prev_face_status = TextureFaceComplete(first_face,
+ face_index,
+ info.target,
+ info.internal_format,
+ info.width,
+ info.height,
+ info.depth,
+ info.format,
+ info.type);
+ bool new_face_status = TextureFaceComplete(first_face,
+ face_index,
+ target,
+ internal_format,
+ width,
+ height,
+ depth,
+ format,
+ type);
+ if (prev_face_status != new_face_status)
+ num_complete_faces_ += new_face_status ? 1 : -1;
+
+ // Only need to validate all faces if the first face is changing.
+ if (face_index != 0)
+ break;
+ }
+ }
+
+ // Update incomplete mip counter.
+ const Texture::LevelInfo& level0_face = level_infos_[face_index][0];
+ const GLsizei num_mip_levels = num_mip_levels_[face_index];
vmiura 2014/10/07 00:13:03 If num_mip_levels changes, for example decreasing,
David Yen 2014/10/09 20:20:16 No longer relevant, using dirty bit now.
+ for (GLsizei i = static_cast<GLsizei>(level); i < num_mip_levels; ++i) {
+ bool prev_mip_status = TextureMipComplete(level0_face,
+ info.target,
+ i,
+ info.internal_format,
+ info.width,
+ info.height,
+ info.depth,
+ info.format,
+ info.type);
+ bool new_mip_status = TextureMipComplete(level0_face,
+ target,
+ i,
+ internal_format,
+ width,
+ height,
+ depth,
+ format,
+ type);
+ if (prev_mip_status != new_mip_status)
+ num_incomplete_mips_ += new_mip_status ? -1 : 1;
vmiura 2014/10/07 00:13:03 As above, I'm not sure we will count correctly whe
David Yen 2014/10/09 20:20:16 No longer relevant, using dirty bit now.
+
+ // Only need to validate all faces if the first face is changing.
+ if (face_index != 0)
+ break;
+ }
+ }
+
info.target = target;
info.level = level;
info.internal_format = internal_format;
@@ -700,7 +840,7 @@ GLenum Texture::SetParameterf(
void Texture::Update(const FeatureInfo* feature_info) {
// Update npot status.
// Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
- npot_ = target_ == GL_TEXTURE_EXTERNAL_OES;
+ npot_ = (target_ == GL_TEXTURE_EXTERNAL_OES) || (num_npot_faces_ > 0);
if (level_infos_.empty()) {
texture_complete_ = false;
@@ -708,74 +848,29 @@ void Texture::Update(const FeatureInfo* feature_info) {
return;
}
- // checks that the first mip of any face is npot.
- for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
- const Texture::LevelInfo& info = level_infos_[ii][0];
- if (GLES2Util::IsNPOT(info.width) ||
- GLES2Util::IsNPOT(info.height) ||
- GLES2Util::IsNPOT(info.depth)) {
- npot_ = true;
- break;
- }
- }
-
// Update texture_complete and cube_complete status.
const Texture::LevelInfo& first_face = level_infos_[0][0];
- int levels_needed = TextureManager::ComputeMipMapCount(
- target_, first_face.width, first_face.height, first_face.depth);
+ int levels_needed = num_mip_levels_[0];
texture_complete_ =
max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0;
cube_complete_ = (level_infos_.size() == 6) &&
- (first_face.width == first_face.height);
+ (first_face.width == first_face.height) &&
+ (num_complete_faces_ == 6);
if (first_face.width == 0 || first_face.height == 0) {
texture_complete_ = false;
- }
- if (first_face.type == GL_FLOAT &&
- !feature_info->feature_flags().enable_texture_float_linear &&
- (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
- mag_filter_ != GL_NEAREST)) {
+ } else if (first_face.type == GL_FLOAT &&
+ !feature_info->feature_flags().enable_texture_float_linear &&
+ (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
+ mag_filter_ != GL_NEAREST)) {
texture_complete_ = false;
} else if (first_face.type == GL_HALF_FLOAT_OES &&
!feature_info->feature_flags().enable_texture_half_float_linear &&
(min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
mag_filter_ != GL_NEAREST)) {
texture_complete_ = false;
- }
- for (size_t ii = 0;
- ii < level_infos_.size() && (cube_complete_ || texture_complete_);
- ++ii) {
- const Texture::LevelInfo& level0 = level_infos_[ii][0];
- if (level0.target == 0 ||
- level0.width != first_face.width ||
- level0.height != first_face.height ||
- level0.depth != 1 ||
- level0.internal_format != first_face.internal_format ||
- level0.format != first_face.format ||
- level0.type != first_face.type) {
- cube_complete_ = false;
- }
- // Get level0 dimensions
- GLsizei width = level0.width;
- GLsizei height = level0.height;
- GLsizei depth = level0.depth;
- for (GLint jj = 1; jj < levels_needed; ++jj) {
- // compute required size for mip.
- width = std::max(1, width >> 1);
- height = std::max(1, height >> 1);
- depth = std::max(1, depth >> 1);
- const Texture::LevelInfo& info = level_infos_[ii][jj];
- if (info.target == 0 ||
- info.width != width ||
- info.height != height ||
- info.depth != depth ||
- info.internal_format != level0.internal_format ||
- info.format != level0.format ||
- info.type != level0.type) {
- texture_complete_ = false;
- break;
- }
- }
+ } else if (num_incomplete_mips_ > 0) {
+ texture_complete_ = false;
}
}
@@ -786,8 +881,7 @@ bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) {
}
const Texture::LevelInfo& first_face = level_infos_[0][0];
- int levels_needed = TextureManager::ComputeMipMapCount(
- target_, first_face.width, first_face.height, first_face.depth);
+ int levels_needed = num_mip_levels_[0];
for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
for (GLint jj = 0; jj < levels_needed; ++jj) {
« gpu/command_buffer/service/texture_manager.h ('K') | « gpu/command_buffer/service/texture_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698