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

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

Issue 558513003: command_buffer: Batch command processing to reduce handler overheads. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 6 years, 3 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/gles2_cmd_decoder.cc
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index d0b1c69ee505c718602fb41638fbaa866af50cb8..786765c2b54ed440df5280ade85e71e8f8db547c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -572,6 +572,11 @@ class GLES2DecoderImpl : public GLES2Decoder,
unsigned int arg_count,
const void* args) OVERRIDE;
+ virtual error::Error DoCommands(unsigned int num_commands,
+ const void* buffer,
+ int num_entries,
+ int* entries_processed) OVERRIDE;
+
// Overridden from AsyncAPIInterface.
virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
@@ -1639,6 +1644,10 @@ class GLES2DecoderImpl : public GLES2Decoder,
return error::kNoError;
}
+ // Set remaining commands to process to 0 to force DoCommands to return
+ // and allow context preemption and GPU watchdog checks in GpuScheduler().
+ void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
+
void ProcessPendingReadPixels();
void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
@@ -1760,6 +1769,9 @@ class GLES2DecoderImpl : public GLES2Decoder,
int frame_number_;
+ // Number of commands remaining to be processed in DoCommands().
+ int commands_to_process_;
+
bool has_robustness_extension_;
GLenum reset_status_;
bool reset_by_robustness_extension_;
@@ -3748,62 +3760,114 @@ const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
}
-// Decode command with its arguments, and call the corresponding GL function.
-// Note: args is a pointer to the command buffer. As such, it could be changed
-// by a (malicious) client at any time, so if validation has to happen, it
-// should operate on a copy of them.
-error::Error GLES2DecoderImpl::DoCommand(
- unsigned int command,
- unsigned int arg_count,
- const void* cmd_data) {
+// Decode a command, and call the corresponding GL functions.
+// NOTE: DoCommand() is slower than calling DoCommands() on larger batches
+// of commands at once, and is now only used for tests that need to track
+// individual commands.
+error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
+ unsigned int arg_count,
+ const void* cmd_data) {
+ return DoCommands(1, cmd_data, arg_count + 1, 0);
+}
+
+// Decode multiple commands, and call the corresponding GL functions.
+// NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
+// changed by a (malicious) client at any time, so if validation has to happen,
+// it should operate on a copy of them.
+// NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
+// interest of performance in this critical execution loop.
+error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
+ const void* buffer,
+ int num_entries,
+ int* entries_processed) {
+ commands_to_process_ = num_commands;
error::Error result = error::kNoError;
- if (log_commands()) {
- // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
- // VLOG(1), no luck.
- LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
- << GetCommandName(command);
- }
- unsigned int command_index = command - kStartPoint - 1;
- if (command_index < arraysize(command_info)) {
- const CommandInfo& info = command_info[command_index];
- unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
- if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
- (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
- bool doing_gpu_trace = false;
- if (gpu_trace_commands_) {
- if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
- doing_gpu_trace = true;
- gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
+ const CommandBufferEntry* cmd_data =
+ static_cast<const CommandBufferEntry*>(buffer);
+ int process_pos = 0;
+ unsigned int command = 0;
+
+ while (process_pos < num_entries && result == error::kNoError &&
+ commands_to_process_--) {
+ const unsigned int size = cmd_data->value_header.size;
+ command = cmd_data->value_header.command;
+
+ if (size == 0) {
+ result = error::kInvalidSize;
+ break;
+ }
+
+ if (static_cast<int>(size) + process_pos > num_entries) {
+ result = error::kOutOfBounds;
+ break;
+ }
+
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
+ GetCommandName(command));
+
+ if (log_commands()) {
+ LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
+ << "cmd: " << GetCommandName(command);
+ }
+
+ const unsigned int arg_count = size - 1;
+ unsigned int command_index = command - kStartPoint - 1;
+ if (command_index < arraysize(command_info)) {
+ const CommandInfo& info = command_info[command_index];
+ unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
+ if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
+ (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
+ bool doing_gpu_trace = false;
+ if (gpu_trace_commands_) {
+ if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
+ doing_gpu_trace = true;
+ gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
+ }
}
- }
- uint32 immediate_data_size =
- (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
+ uint32 immediate_data_size = (arg_count - info_arg_count) *
+ sizeof(CommandBufferEntry); // NOLINT
- result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
+ result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
- if (doing_gpu_trace)
- gpu_tracer_->End(kTraceDecoder);
+ if (doing_gpu_trace)
+ gpu_tracer_->End(kTraceDecoder);
- if (debug()) {
- GLenum error;
- while ((error = glGetError()) != GL_NO_ERROR) {
- LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
- << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
- << GetCommandName(command);
- LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
+ if (debug()) {
+ GLenum error;
+ while ((error = glGetError()) != GL_NO_ERROR) {
+ LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
+ << "GL ERROR: " << GLES2Util::GetStringEnum(error)
+ << " : " << GetCommandName(command);
+ LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
+ }
}
+ } else {
+ result = error::kInvalidArguments;
}
} else {
- result = error::kInvalidArguments;
+ result = DoCommonCommand(command, arg_count, cmd_data);
}
- } else {
- result = DoCommonCommand(command, arg_count, cmd_data);
- }
- if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
+ if (result == error::kNoError &&
+ current_decoder_error_ != error::kNoError) {
result = current_decoder_error_;
current_decoder_error_ = error::kNoError;
+ }
+
+ if (result != error::kDeferCommandUntilLater) {
+ process_pos += size;
+ cmd_data += size;
+ }
+ }
+
+ if (entries_processed)
+ *entries_processed = process_pos;
+
+ if (error::IsError(result)) {
+ LOG(ERROR) << "Error: " << result << " for Command "
+ << GetCommandName(command);
}
+
return result;
}
@@ -5698,6 +5762,10 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
program_manager()->ClearUniforms(program);
}
}
+
+ // LinkProgram can be very slow. Exit command processing to allow for
+ // context preemption and GPU watchdog checks.
+ ExitCommandProcessingEarly();
};
void GLES2DecoderImpl::DoTexParameterf(
@@ -6826,7 +6894,11 @@ void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
translator,
feature_info_->feature_flags().angle_translated_shader_source ?
ProgramManager::kANGLE : ProgramManager::kGL);
-};
+
+ // CompileShader can be very slow. Exit command processing to allow for
+ // context preemption and GPU watchdog checks.
+ ExitCommandProcessingEarly();
+}
void GLES2DecoderImpl::DoGetShaderiv(
GLuint shader_id, GLenum pname, GLint* params) {
@@ -8325,6 +8397,10 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
texture_ref, target, level, internal_format,
width, height, 1, border, 0, 0, true);
}
+
+ // This may be a slow command. Exit command processing to allow for
+ // context preemption and GPU watchdog checks.
+ ExitCommandProcessingEarly();
return error::kNoError;
}
@@ -8472,6 +8548,10 @@ error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
pixels, pixels_size};
texture_manager()->ValidateAndDoTexImage2D(
&texture_state_, &state_, &framebuffer_state_, args);
+
+ // This may be a slow command. Exit command processing to allow for
+ // context preemption and GPU watchdog checks.
+ ExitCommandProcessingEarly();
return error::kNoError;
}
@@ -8530,6 +8610,10 @@ void GLES2DecoderImpl::DoCompressedTexSubImage2D(
// CompressedTexImage2D already cleared the texture.
glCompressedTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, image_size, data);
+
+ // This may be a slow command. Exit command processing to allow for
+ // context preemption and GPU watchdog checks.
+ ExitCommandProcessingEarly();
}
static void Clip(
@@ -8675,6 +8759,10 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
texture_ref, target, level, internal_format, width, height, 1,
border, internal_format, GL_UNSIGNED_BYTE, true);
}
+
+ // This may be a slow command. Exit command processing to allow for
+ // context preemption and GPU watchdog checks.
+ ExitCommandProcessingEarly();
}
void GLES2DecoderImpl::DoCopyTexSubImage2D(
@@ -8785,6 +8873,10 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
destX, destY, copyX, copyY,
copyWidth, copyHeight);
}
+
+ // This may be a slow command. Exit command processing to allow for
+ // context preemption and GPU watchdog checks.
+ ExitCommandProcessingEarly();
}
bool GLES2DecoderImpl::ValidateTexSubImage2D(
@@ -8915,6 +9007,10 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, type, data);
}
texture_manager()->SetLevelCleared(texture_ref, target, level, true);
+
+ // This may be a slow command. Exit command processing to allow for
+ // context preemption and GPU watchdog checks.
+ ExitCommandProcessingEarly();
return error::kNoError;
}
@@ -9401,6 +9497,10 @@ void GLES2DecoderImpl::DoSwapBuffers() {
LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
}
}
+
+ // This may be a slow command. Exit command processing to allow for
+ // context preemption and GPU watchdog checks.
+ ExitCommandProcessingEarly();
}
error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
« no previous file with comments | « gpu/command_buffer/service/common_decoder_unittest.cc ('k') | gpu/command_buffer/service/gles2_cmd_decoder_mock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698