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

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

Issue 1963683002: Fix unpacking overlapping unpack buffer rows on NVIDIA GL (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Slight refactoring and change Linux expectations Created 4 years, 7 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
« no previous file with comments | « gpu/command_buffer/service/texture_manager.h ('k') | gpu/config/gpu_driver_bug_list_json.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 e9dab99cd47e1875e0a1ea3c1546e83f4b1531e0..b12b4355a809e93ddec592b4932f1d7486f56842 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -2394,20 +2394,42 @@ void TextureManager::ValidateAndDoTexImage(
}
}
+ if (texture_state->unpack_overlapping_rows_separately_unpack_buffer &&
+ buffer) {
+ ContextState::Dimension dimension =
+ (args.command_type == DoTexImageArguments::kTexImage3D)
+ ? ContextState::k3D
+ : ContextState::k2D;
+ const PixelStoreParams unpack_params(state->GetUnpackParams(dimension));
+ if (unpack_params.row_length != 0 &&
+ unpack_params.row_length < args.width) {
+ // The rows overlap in unpack memory. Upload the texture row by row to
+ // work around driver bug.
+
+ ReserveTexImageToBeFilled(texture_state, state, framebuffer_state,
+ function_name, texture_ref, args);
+
+ DoTexSubImageArguments sub_args = {
+ args.target, args.level, 0, 0, 0, args.width, args.height, args.depth,
+ args.format, args.type, args.pixels, args.pixels_size, args.padding,
+ args.command_type == DoTexImageArguments::kTexImage3D
+ ? DoTexSubImageArguments::kTexSubImage3D
+ : DoTexSubImageArguments::kTexSubImage2D};
+ DoTexSubImageRowByRowWorkaround(texture_state, state, sub_args,
+ unpack_params);
+
+ SetLevelCleared(texture_ref, args.target, args.level, true);
+ return;
+ }
+ }
+
if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) {
uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) {
// In ValidateTexImage(), we already made sure buffer size is no less
// than offset + pixels_size.
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, nullptr);
- DoTexImageArguments new_args = args;
- new_args.pixels = nullptr;
- // pixels_size might be incorrect, but it's not used in this case.
- DoTexImage(texture_state, state, framebuffer_state, function_name,
- texture_ref, new_args);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->service_id());
- state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
+ ReserveTexImageToBeFilled(texture_state, state, framebuffer_state,
+ function_name, texture_ref, args);
DoTexSubImageArguments sub_args = {
args.target, args.level, 0, 0, 0, args.width, args.height, args.depth,
@@ -2425,6 +2447,25 @@ void TextureManager::ValidateAndDoTexImage(
function_name, texture_ref, args);
}
+void TextureManager::ReserveTexImageToBeFilled(
+ DecoderTextureState* texture_state,
+ ContextState* state,
+ DecoderFramebufferState* framebuffer_state,
+ const char* function_name,
+ TextureRef* texture_ref,
+ const DoTexImageArguments& args) {
+ Buffer* buffer = state->bound_pixel_unpack_buffer.get();
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, nullptr);
+ DoTexImageArguments new_args = args;
+ new_args.pixels = nullptr;
+ // pixels_size might be incorrect, but it's not used in this case.
+ DoTexImage(texture_state, state, framebuffer_state, function_name,
+ texture_ref, new_args);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->service_id());
+ state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
+}
+
bool TextureManager::ValidateTexSubImage(ContextState* state,
const char* function_name,
const DoTexSubImageArguments& args,
@@ -2572,6 +2613,24 @@ void TextureManager::ValidateAndDoTexSubImage(
}
Buffer* buffer = state->bound_pixel_unpack_buffer.get();
+
+ if (texture_state->unpack_overlapping_rows_separately_unpack_buffer &&
+ buffer) {
+ ContextState::Dimension dimension =
+ (args.command_type == DoTexSubImageArguments::kTexSubImage3D)
+ ? ContextState::k3D
+ : ContextState::k2D;
+ const PixelStoreParams unpack_params(state->GetUnpackParams(dimension));
+ if (unpack_params.row_length != 0 &&
+ unpack_params.row_length < args.width) {
+ // The rows overlap in unpack memory. Upload the texture row by row to
+ // work around driver bug.
+ DoTexSubImageRowByRowWorkaround(texture_state, state, args,
+ unpack_params);
+ return;
+ }
+ }
+
if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) {
uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) {
@@ -2719,6 +2778,58 @@ void TextureManager::DoTexSubImageWithAlignmentWorkaround(
DCHECK_EQ(ToGLuint(args.pixels) + args.pixels_size, offset);
}
+void TextureManager::DoTexSubImageRowByRowWorkaround(
+ DecoderTextureState* texture_state,
+ ContextState* state,
+ const DoTexSubImageArguments& args,
+ const PixelStoreParams& unpack_params) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ DCHECK_EQ(0, state->unpack_skip_pixels);
+ DCHECK_EQ(0, state->unpack_skip_rows);
+ DCHECK_EQ(0, state->unpack_skip_images);
+
+ GLenum format = AdjustTexFormat(args.format);
+
+ GLsizei row_bytes = unpack_params.row_length *
+ GLES2Util::ComputeImageGroupSize(format, args.type);
+ GLsizei alignment_diff = row_bytes % unpack_params.alignment;
+ if (alignment_diff != 0) {
+ row_bytes += unpack_params.alignment - alignment_diff;
+ }
+ DCHECK_EQ(0, row_bytes % unpack_params.alignment);
+ if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) {
+ GLsizei image_height = args.height;
+ if (unpack_params.image_height != 0) {
+ image_height = unpack_params.image_height;
+ }
+ GLsizei image_bytes = row_bytes * image_height;
+ for (GLsizei image = 0; image < args.depth; ++image) {
+ GLsizei image_byte_offset = image * image_bytes;
+ for (GLsizei row = 0; row < args.height; ++row) {
+ GLsizei byte_offset = image_byte_offset + row * row_bytes;
+ const GLubyte* row_pixels =
+ reinterpret_cast<const GLubyte*>(args.pixels) + byte_offset;
+ glTexSubImage3D(args.target, args.level, args.xoffset,
+ row + args.yoffset, image + args.zoffset, args.width, 1,
+ 1, format, args.type, row_pixels);
+ }
+ }
+ } else {
+ for (GLsizei row = 0; row < args.height; ++row) {
+ GLsizei byte_offset = row * row_bytes;
+ const GLubyte* row_pixels =
+ reinterpret_cast<const GLubyte*>(args.pixels) + byte_offset;
+ glTexSubImage2D(args.target, args.level, args.xoffset, row + args.yoffset,
+ args.width, 1, format, args.type, row_pixels);
+ }
+ }
+
+ // Restore unpack state
+ glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_params.alignment);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_params.row_length);
+}
+
GLenum TextureManager::AdjustTexInternalFormat(GLenum format) const {
if (feature_info_->gl_version_info().is_desktop_core_profile) {
const Texture::CompatibilitySwizzle* swizzle =
« no previous file with comments | « gpu/command_buffer/service/texture_manager.h ('k') | gpu/config/gpu_driver_bug_list_json.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698