gpu: Add the ability to wait on upload completion.
Patch originally by Eric Penner <[email protected]>.
We currently have high latency if need to wait for uploads
in the renderer client. If we can do a shallow client side
wait it will be much better. This is effectively the
same as doing synchronous uploads, but exposes less driver
bug surface area then mixing uploads across threads.
BUG=161828, 178634
Review URL: https://chromiumcodereview.appspot.com/12210129
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186190 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 2ec5a2e..e826abd0 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -2296,6 +2296,13 @@
'extension': True,
'chromium': True,
},
+ 'WaitAsyncTexImage2DCHROMIUM': {
+ 'type': 'Manual',
+ 'immediate': False,
+ 'client_test': False,
+ 'extension': True,
+ 'chromium': True,
+ },
'DiscardFramebufferEXT': {
'type': 'PUTn',
'count': 1,
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index d56df6fd..8ed8d9d8 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -712,6 +712,9 @@
target, level, internalformat, width, height, border, format, type,
pixels);
}
+void GLES2WaitAsyncTexImage2DCHROMIUM(GLenum target) {
+ gles2::GetGLContext()->WaitAsyncTexImage2DCHROMIUM(target);
+}
void GLES2DiscardFramebufferEXT(
GLenum target, GLsizei count, const GLenum* attachments) {
gles2::GetGLContext()->DiscardFramebufferEXT(target, count, attachments);
@@ -1053,6 +1056,8 @@
glAsyncTexSubImage2DCHROMIUM), },
{ "glAsyncTexImage2DCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
glAsyncTexImage2DCHROMIUM), },
+ { "glWaitAsyncTexImage2DCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
+ glWaitAsyncTexImage2DCHROMIUM), },
{ "glDiscardFramebufferEXT", reinterpret_cast<GLES2FunctionPointer>(
glDiscardFramebufferEXT), },
{ "glLoseContextCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index c9c8d7f..ec8b078 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -2035,6 +2035,14 @@
}
}
+ void WaitAsyncTexImage2DCHROMIUM(GLenum target) {
+ gles2::cmds::WaitAsyncTexImage2DCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::WaitAsyncTexImage2DCHROMIUM>();
+ if (c) {
+ c->Init(target);
+ }
+ }
+
void DiscardFramebufferEXT(
GLenum target, GLsizei count, uint32 attachments_shm_id,
uint32 attachments_shm_offset) {
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 600c02f..e19911c81 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -3439,6 +3439,14 @@
return;
}
+void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
+ << GLES2Util::GetStringTextureTarget(target) << ")");
+ helper_->WaitAsyncTexImage2DCHROMIUM(target);
+ CheckGLError();
+}
+
// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index e4a63822..1ad32d8 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -519,6 +519,8 @@
GLsizei height, GLint border, GLenum format, GLenum type,
const void* pixels) OVERRIDE;
+virtual void WaitAsyncTexImage2DCHROMIUM(GLenum target) OVERRIDE;
+
virtual void DiscardFramebufferEXT(
GLenum target, GLsizei count, const GLenum* attachments) OVERRIDE;
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index 8aafc7f..24bf6f0 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -300,6 +300,7 @@
GLenum target, GLint level, GLint internalformat, GLsizei width,
GLsizei height, GLint border, GLenum format, GLenum type,
const void* pixels) = 0;
+virtual void WaitAsyncTexImage2DCHROMIUM(GLenum target) = 0;
virtual void DiscardFramebufferEXT(
GLenum target, GLsizei count, const GLenum* attachments) = 0;
virtual void LoseContextCHROMIUM(GLenum current, GLenum other) = 0;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 80e6c10..af286b3 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -331,6 +331,7 @@
GLenum target, GLint level, GLint internalformat, GLsizei width,
GLsizei height, GLint border, GLenum format, GLenum type,
const void* pixels) OVERRIDE;
+virtual void WaitAsyncTexImage2DCHROMIUM(GLenum target) OVERRIDE;
virtual void DiscardFramebufferEXT(
GLenum target, GLsizei count, const GLenum* attachments) OVERRIDE;
virtual void LoseContextCHROMIUM(GLenum current, GLenum other) OVERRIDE;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
index f097e8cb..4add6c4 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -623,6 +623,8 @@
GLsizei /* width */, GLsizei /* height */, GLint /* border */,
GLenum /* format */, GLenum /* type */, const void* /* pixels */) {
}
+void GLES2InterfaceStub::WaitAsyncTexImage2DCHROMIUM(GLenum /* target */) {
+}
void GLES2InterfaceStub::DiscardFramebufferEXT(
GLenum /* target */, GLsizei /* count */,
const GLenum* /* attachments */) {
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index da02881..6883771 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -331,6 +331,7 @@
GLenum target, GLint level, GLint internalformat, GLsizei width,
GLsizei height, GLint border, GLenum format, GLenum type,
const void* pixels) OVERRIDE;
+virtual void WaitAsyncTexImage2DCHROMIUM(GLenum target) OVERRIDE;
virtual void DiscardFramebufferEXT(
GLenum target, GLsizei count, const GLenum* attachments) OVERRIDE;
virtual void LoseContextCHROMIUM(GLenum current, GLenum other) OVERRIDE;
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
index 8f87a40d..a6bf01e 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -1153,6 +1153,11 @@
pixels);
}
+void GLES2TraceImplementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::WaitAsyncTexImage2DCHROMIUM"); // NOLINT
+ gl_->WaitAsyncTexImage2DCHROMIUM(target);
+}
+
void GLES2TraceImplementation::DiscardFramebufferEXT(
GLenum target, GLsizei count, const GLenum* attachments) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DiscardFramebufferEXT");
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index 08d33d9..661ffeb 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -205,6 +205,7 @@
GL_APICALL void GL_APIENTRY glTraceEndCHROMIUM (void);
GL_APICALL void GL_APIENTRY glAsyncTexSubImage2DCHROMIUM (GLenumTextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenumTextureFormat format, GLenumPixelType type, const void* data);
GL_APICALL void GL_APIENTRY glAsyncTexImage2DCHROMIUM (GLenumTextureTarget target, GLint level, GLintTextureInternalFormat internalformat, GLsizei width, GLsizei height, GLintTextureBorder border, GLenumTextureFormat format, GLenumPixelType type, const void* pixels);
+GL_APICALL void GL_APIENTRY glWaitAsyncTexImage2DCHROMIUM (GLenumTextureTarget target);
GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei count, const GLenum* attachments);
GL_APICALL void GL_APIENTRY glLoseContextCHROMIUM (GLenum current, GLenum other);
GL_APICALL void GL_APIENTRY glWaitSyncPointCHROMIUM (GLuint sync_point);
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index dea5003..7597a51 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -10730,6 +10730,40 @@
COMPILE_ASSERT(offsetof(AsyncTexImage2DCHROMIUM, pixels_shm_offset) == 40,
OffsetOf_AsyncTexImage2DCHROMIUM_pixels_shm_offset_not_40);
+struct WaitAsyncTexImage2DCHROMIUM {
+ typedef WaitAsyncTexImage2DCHROMIUM ValueType;
+ static const CommandId kCmdId = kWaitAsyncTexImage2DCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+ static uint32 ComputeSize() {
+ return static_cast<uint32>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() {
+ header.SetCmd<ValueType>();
+ }
+
+ void Init(GLenum _target) {
+ SetHeader();
+ target = _target;
+ }
+
+ void* Set(void* cmd, GLenum _target) {
+ static_cast<ValueType*>(cmd)->Init(_target);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32 target;
+};
+
+COMPILE_ASSERT(sizeof(WaitAsyncTexImage2DCHROMIUM) == 8,
+ Sizeof_WaitAsyncTexImage2DCHROMIUM_is_not_8);
+COMPILE_ASSERT(offsetof(WaitAsyncTexImage2DCHROMIUM, header) == 0,
+ OffsetOf_WaitAsyncTexImage2DCHROMIUM_header_not_0);
+COMPILE_ASSERT(offsetof(WaitAsyncTexImage2DCHROMIUM, target) == 4,
+ OffsetOf_WaitAsyncTexImage2DCHROMIUM_target_not_4);
+
struct DiscardFramebufferEXT {
typedef DiscardFramebufferEXT ValueType;
static const CommandId kCmdId = kDiscardFramebufferEXT;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index 9271d17..bb47907 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -4366,6 +4366,20 @@
next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, WaitAsyncTexImage2DCHROMIUM) {
+ cmds::WaitAsyncTexImage2DCHROMIUM& cmd =
+ *GetBufferAs<cmds::WaitAsyncTexImage2DCHROMIUM>();
+ void* next_cmd = cmd.Set(
+ &cmd,
+ static_cast<GLenum>(11));
+ EXPECT_EQ(static_cast<uint32>(cmds::WaitAsyncTexImage2DCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+ CheckBytesWrittenMatchesExpectedSize(
+ next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, DiscardFramebufferEXT) {
cmds::DiscardFramebufferEXT& cmd =
*GetBufferAs<cmds::DiscardFramebufferEXT>();
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index 6e96efd..0c22a37c 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -245,10 +245,11 @@
OP(TraceEndCHROMIUM) /* 488 */ \
OP(AsyncTexSubImage2DCHROMIUM) /* 489 */ \
OP(AsyncTexImage2DCHROMIUM) /* 490 */ \
- OP(DiscardFramebufferEXT) /* 491 */ \
- OP(DiscardFramebufferEXTImmediate) /* 492 */ \
- OP(LoseContextCHROMIUM) /* 493 */ \
- OP(WaitSyncPointCHROMIUM) /* 494 */ \
+ OP(WaitAsyncTexImage2DCHROMIUM) /* 491 */ \
+ OP(DiscardFramebufferEXT) /* 492 */ \
+ OP(DiscardFramebufferEXTImmediate) /* 493 */ \
+ OP(LoseContextCHROMIUM) /* 494 */ \
+ OP(WaitSyncPointCHROMIUM) /* 495 */ \
enum CommandId {
kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h b/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h
index b716e70e..7432737 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h
@@ -43,6 +43,7 @@
void(gfx::AsyncPixelTransferState*,
const AsyncTexSubImage2DParams& tex_params,
const AsyncMemoryParams& mem_params));
+ MOCK_METHOD1(WaitForTransferCompletion, void(gfx::AsyncPixelTransferState*));
MOCK_METHOD0(GetTextureUploadCount, uint32());
MOCK_METHOD0(GetTotalTextureUploadTime, base::TimeDelta());
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 77aa601..ed177256 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -10151,6 +10151,26 @@
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
+ uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
+ TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
+ GLenum target = static_cast<GLenum>(c.target);
+
+ if (GL_TEXTURE_2D != target) {
+ SetGLError(GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
+ return error::kNoError;
+ }
+ Texture* info = GetTextureInfoForTarget(target);
+ if (!info) {
+ SetGLError(GL_INVALID_OPERATION,
+ "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
+ return error::kNoError;
+ }
+ async_pixel_transfer_delegate_->WaitForTransferCompletion(
+ info->GetAsyncTransferState());
+ return error::kNoError;
+}
+
// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index b4b54cc..bae3717 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -7979,6 +7979,8 @@
AsyncTexSubImage2DCHROMIUM texsubimage_cmd;
texsubimage_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGBA,
GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset);
+ WaitAsyncTexImage2DCHROMIUM wait_cmd;
+ wait_cmd.Init(GL_TEXTURE_2D);
gfx::AsyncTexImage2DParams teximage_params =
{GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE};
@@ -8085,6 +8087,14 @@
EXPECT_TRUE(info->SafeToRenderFrom());
}
+ // WaitAsyncTexSubImage2D
+ {
+ // Command succeeds.
+ EXPECT_CALL(*delegate, WaitForTransferCompletion(state));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(wait_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ }
+
decoder_->SetAsyncPixelTransferDelegate(NULL);
info->SetAsyncTransferState(scoped_ptr<gfx::AsyncPixelTransferState>());
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
index a8399c6..6294b93 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
@@ -64,6 +64,8 @@
// TODO(gman): AsyncTexImage2DCHROMIUM
+// TODO(gman): WaitAsyncTexImage2DCHROMIUM
+
// TODO(gman): DiscardFramebufferEXT
// TODO(gman): DiscardFramebufferEXTImmediate
// TODO(gman): LoseContextCHROMIUM