diff options
author | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-17 23:48:27 +0000 |
---|---|---|
committer | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-17 23:48:27 +0000 |
commit | 6a25ae42f4c34047298ad5bf26ec14e6bafb5805 (patch) | |
tree | 18c94e94db86a3892a00de8fef82f324ec117b9e /gpu | |
parent | c53d16f1736e97da9d8de7c55b2c861aab9080b2 (diff) | |
download | chromium_src-6a25ae42f4c34047298ad5bf26ec14e6bafb5805.zip chromium_src-6a25ae42f4c34047298ad5bf26ec14e6bafb5805.tar.gz chromium_src-6a25ae42f4c34047298ad5bf26ec14e6bafb5805.tar.bz2 |
Re-land: gpu: Add CHROMIUM_sync_query extension.
This adds a GL_COMMANDS_COMPLETED_CHROMIUM query target that provide
a finer granularity of synchronizing GL command completion than offered
by glFinish().
BUG=269808,356871,273274
TEST=gpu_unittests --gtest_filter=GLES2DecoderManualInitTest.BeginEndQueryEXTCommandsCompletedCHROMIUM
Review URL: https://codereview.chromium.org/238933003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@264675 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_query.txt | 53 | ||||
-rw-r--r-- | gpu/GLES2/gl2extchromium.h | 9 | ||||
-rwxr-xr-x | gpu/command_buffer/build_gles2_cmd_buffer.py | 1 | ||||
-rw-r--r-- | gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h | 10 | ||||
-rw-r--r-- | gpu/command_buffer/service/feature_info.cc | 6 | ||||
-rw-r--r-- | gpu/command_buffer/service/feature_info.h | 1 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 8 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc | 76 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h | 3 | ||||
-rw-r--r-- | gpu/command_buffer/service/query_manager.cc | 53 |
10 files changed, 217 insertions, 3 deletions
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_query.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_query.txt new file mode 100644 index 0000000..98763d0 --- /dev/null +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_query.txt @@ -0,0 +1,53 @@ +Name + + CHROMIUM_sync_query + +Name Strings + + GL_CHROMIUM_sync_query + +Version + + Last Modifed Date: April 15, 2014 + +Dependencies + + OpenGL ES 2.0 is required. + + EXT_occlusion_query_boolean is required. + +Overview + + This extension provides a query mechanism that allow for synchronization + between the host CPU and the GPU, which may be accessing the same + resources (typically memory). + + This extension is useful in conjunction with CHROMIUM_map_image to + determine when it is safe to access a mapped image. Once the result of + a COMMANDS_COMPLETED_CHROMIUM query is available, all drawing commands + issued before the query must have finished. This ensures that the memory + corresponding to the issued commands can be safely modified (assuming no + other outstanding drawing commands are issued subsequent to the query). + +New Procedures and Functions + + None. + +Errors + + None. + +New Tokens + + Accepted by the <target> parameter of BeginQueryEXT, EndQueryEXT, + and GetQueryivEXT: + + COMMANDS_COMPLETED_CHROMIUM 0x84F7 + +New State + + None. + +Revision History + + 4/15/2014 Documented the extension diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h index db4f12f..0bdf717 100644 --- a/gpu/GLES2/gl2extchromium.h +++ b/gpu/GLES2/gl2extchromium.h @@ -692,6 +692,15 @@ typedef void(GL_APIENTRYP PFNGLSCHEDULEOVERLAYPLANECHROMIUMPROC)( GLfloat uv_height); #endif /* GL_CHROMIUM_schedule_overlay_plane */ +/* GL_CHROMIUM_sync_query */ +#ifndef GL_CHROMIUM_sync_query +#define GL_CHROMIUM_sync_query 1 + +#ifndef GL_COMMANDS_COMPLETED_CHROMIUM +#define GL_COMMANDS_COMPLETED_CHROMIUM 0x84F7 +#endif +#endif /* GL_CHROMIUM_sync_query */ + #ifdef __cplusplus } #endif diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 84d70c0..7105edf 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -841,6 +841,7 @@ _ENUM_LISTS = { 'GL_LATENCY_QUERY_CHROMIUM', 'GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM', 'GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM', + 'GL_COMMANDS_COMPLETED_CHROMIUM', ], }, 'RenderBufferParameter': { diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index 62f1c308..e9f4f69 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -179,6 +179,7 @@ static const GLES2Util::EnumToString enum_to_string_table[] = { {0x84F4, "GL_FENCE_CONDITION_NV", }, {0x8366, "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT", }, {0x8365, "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT", }, + {0x84F7, "GL_COMMANDS_COMPLETED_CHROMIUM", }, {0x881E, "GL_LUMINANCE16F_EXT", }, {0x84FA, "GL_UNSIGNED_INT_24_8_OES", }, {0x881F, "GL_LUMINANCE_ALPHA16F_EXT", }, @@ -353,6 +354,7 @@ static const GLES2Util::EnumToString enum_to_string_table[] = { {0x8C93, "GL_ATC_RGBA_EXPLICIT_ALPHA_AMD", }, {0x00000002, "GL_CONTEXT_FLAG_DEBUG_BIT_KHR", }, {0x00000001, "GL_SYNC_FLUSH_COMMANDS_BIT_APPLE", }, + {0x9248, "GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM", }, {0x00000004, "GL_COLOR_BUFFER_BIT2_QCOM", }, {0x1702, "GL_TEXTURE", }, {0x00000008, "GL_COLOR_BUFFER_BIT3_QCOM", }, @@ -385,6 +387,7 @@ static const GLES2Util::EnumToString enum_to_string_table[] = { {0x8DF6, "GL_UNSIGNED_INT_10_10_10_2_OES", }, {0x8230, "GL_RG32F_EXT", }, {0x8DF7, "GL_INT_10_10_10_2_OES", }, + {0x9246, "GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM", }, {0x8B69, "GL_FLOAT_MAT4x2_NV", }, {0x812D, "GL_CLAMP_TO_BORDER_NV", }, {0x812F, "GL_CLAMP_TO_EDGE", }, @@ -604,8 +607,11 @@ static const GLES2Util::EnumToString enum_to_string_table[] = { {0x1F02, "GL_VERSION", }, {0x1F01, "GL_RENDERER", }, {0x1F00, "GL_VENDOR", }, + {0x9247, "GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM", }, {0x2701, "GL_LINEAR_MIPMAP_NEAREST", }, + {0x9245, "GL_OVERLAY_TRANSFORM_NONE_CHROMIUM", }, {0x92B4, "GL_INVERT_OVG_NV", }, + {0x9249, "GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM", }, {0x0B94, "GL_STENCIL_FAIL", }, {0x8B4C, "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS", }, {0x8B4D, "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS", }, @@ -634,6 +640,7 @@ static const GLES2Util::EnumToString enum_to_string_table[] = { {0x1004, "GL_TEXTURE_BORDER_COLOR_NV", }, {0x8B48, "GL_SHADER_OBJECT_EXT", }, {0x912F, "GL_TEXTURE_IMMUTABLE_FORMAT_EXT", }, + {0x924A, "GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM", }, {0x20000000, "GL_MULTISAMPLE_BUFFER_BIT5_QCOM", }, {0x0DE1, "GL_TEXTURE_2D", }, {0x80C9, "GL_BLEND_SRC_RGB", }, @@ -1163,7 +1170,8 @@ std::string GLES2Util::GetStringQueryTarget(uint32 value) { {GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, "GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM"}, {GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, - "GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM"}, }; + "GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM"}, + {GL_COMMANDS_COMPLETED_CHROMIUM, "GL_COMMANDS_COMPLETED_CHROMIUM"}, }; return GLES2Util::GetQualifiedEnumString( string_table, arraysize(string_table), value); } diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 334cec1..15d8ca0 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -110,6 +110,7 @@ FeatureInfo::FeatureFlags::FeatureFlags() : chromium_color_buffer_float_rgba(false), chromium_color_buffer_float_rgb(false), chromium_framebuffer_multisample(false), + chromium_sync_query(false), use_core_framebuffer_multisample(false), multisampled_render_to_texture(false), use_img_for_multisampled_render_to_texture(false), @@ -794,6 +795,11 @@ void FeatureInfo::InitializeFeatures() { AddExtensionString("GL_EXT_discard_framebuffer"); feature_flags_.ext_discard_framebuffer = true; } + + if (ui_gl_fence_works) { + AddExtensionString("GL_CHROMIUM_sync_query"); + feature_flags_.chromium_sync_query = true; + } } void FeatureInfo::AddExtensionString(const std::string& str) { diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index c29a50c..8e9c07c 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h @@ -31,6 +31,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool chromium_color_buffer_float_rgba; bool chromium_color_buffer_float_rgb; bool chromium_framebuffer_multisample; + bool chromium_sync_query; // Use glBlitFramebuffer() and glRenderbufferStorageMultisample() with // GL_EXT_framebuffer_multisample-style semantics, since they are exposed // as core GL functions on this implementation. diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index a886513..d0b040b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -9535,6 +9535,14 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT( case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM: case GL_GET_ERROR_QUERY_CHROMIUM: break; + case GL_COMMANDS_COMPLETED_CHROMIUM: + if (!features().chromium_sync_query) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, "glBeginQueryEXT", + "not enabled for commands completed queries"); + return error::kNoError; + } + break; default: if (!features().occlusion_query_boolean) { LOCAL_SET_GL_ERROR( diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index 19b7292..b367e5c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -7112,6 +7112,7 @@ const QueryType kQueryTypes[] = { { GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, false }, { GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, false }, { GL_GET_ERROR_QUERY_CHROMIUM, false }, + { GL_COMMANDS_COMPLETED_CHROMIUM, false }, { GL_ANY_SAMPLES_PASSED_EXT, true }, }; @@ -7125,7 +7126,7 @@ static void CheckBeginEndQueryBadMemoryFails( // We need to reset the decoder on each iteration, because we lose the // context every time. GLES2DecoderTestBase::InitState init; - init.extensions = "GL_EXT_occlusion_query_boolean"; + init.extensions = "GL_EXT_occlusion_query_boolean GL_ARB_sync"; init.gl_version = "opengl es 2.0"; init.has_alpha = true; init.request_alpha = true; @@ -7160,6 +7161,13 @@ static void CheckBeginEndQueryBadMemoryFails( .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); } + GLsync kGlSync = reinterpret_cast<GLsync>(0xdeadbeef); + if (query_type.type == GL_COMMANDS_COMPLETED_CHROMIUM) { + EXPECT_CALL(*gl, Flush()).RetiresOnSaturation(); + EXPECT_CALL(*gl, FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)) + .WillOnce(Return(kGlSync)) + .RetiresOnSaturation(); + } EndQueryEXT end_cmd; end_cmd.Init(query_type.type, 1); @@ -7175,6 +7183,11 @@ static void CheckBeginEndQueryBadMemoryFails( .WillOnce(SetArgumentPointee<2>(1)) .RetiresOnSaturation(); } + if (query_type.type == GL_COMMANDS_COMPLETED_CHROMIUM) { + EXPECT_CALL(*gl, ClientWaitSync(kGlSync, _, _)) + .WillOnce(Return(GL_ALREADY_SIGNALED)) + .RetiresOnSaturation(); + } QueryManager* query_manager = test->GetDecoder()->GetQueryManager(); ASSERT_TRUE(query_manager != NULL); @@ -7189,6 +7202,8 @@ static void CheckBeginEndQueryBadMemoryFails( .Times(1) .RetiresOnSaturation(); } + if (query_type.type == GL_COMMANDS_COMPLETED_CHROMIUM) + EXPECT_CALL(*gl, DeleteSync(kGlSync)).Times(1).RetiresOnSaturation(); test->ResetDecoder(); } @@ -7276,6 +7291,65 @@ TEST_F(GLES2DecoderTest, BeginEndQueryEXTGetErrorQueryCHROMIUM) { static_cast<GLenum>(sync->result)); } +TEST_F(GLES2DecoderManualInitTest, BeginEndQueryEXTCommandsCompletedCHROMIUM) { + InitState init; + init.extensions = "GL_EXT_occlusion_query_boolean GL_ARB_sync"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); + + GenHelper<GenQueriesEXTImmediate>(kNewClientId); + + BeginQueryEXT begin_cmd; + begin_cmd.Init(GL_COMMANDS_COMPLETED_CHROMIUM, + kNewClientId, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + QueryManager* query_manager = decoder_->GetQueryManager(); + ASSERT_TRUE(query_manager != NULL); + QueryManager::Query* query = query_manager->GetQuery(kNewClientId); + ASSERT_TRUE(query != NULL); + EXPECT_FALSE(query->pending()); + + GLsync kGlSync = reinterpret_cast<GLsync>(0xdeadbeef); + EXPECT_CALL(*gl_, Flush()).RetiresOnSaturation(); + EXPECT_CALL(*gl_, FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)) + .WillOnce(Return(kGlSync)) + .RetiresOnSaturation(); + + EndQueryEXT end_cmd; + end_cmd.Init(GL_COMMANDS_COMPLETED_CHROMIUM, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(end_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(query->pending()); + + EXPECT_CALL(*gl_, ClientWaitSync(kGlSync, _, _)) + .WillOnce(Return(GL_TIMEOUT_EXPIRED)) + .RetiresOnSaturation(); + bool process_success = query_manager->ProcessPendingQueries(); + + EXPECT_TRUE(process_success); + EXPECT_TRUE(query->pending()); + + EXPECT_CALL(*gl_, ClientWaitSync(kGlSync, _, _)) + .WillOnce(Return(GL_ALREADY_SIGNALED)) + .RetiresOnSaturation(); + process_success = query_manager->ProcessPendingQueries(); + + EXPECT_TRUE(process_success); + EXPECT_FALSE(query->pending()); + QuerySync* sync = static_cast<QuerySync*>(shared_memory_address_); + EXPECT_EQ(static_cast<GLenum>(0), static_cast<GLenum>(sync->result)); + + EXPECT_CALL(*gl_, DeleteSync(kGlSync)).Times(1).RetiresOnSaturation(); + ResetDecoder(); +} + TEST_F(GLES2DecoderTest, ProduceAndConsumeTextureCHROMIUM) { Mailbox mailbox = Mailbox::Generate(); diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index ca49ced..d296018 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h @@ -214,7 +214,8 @@ static const GLenum valid_query_target_table[] = { GL_COMMANDS_ISSUED_CHROMIUM, GL_LATENCY_QUERY_CHROMIUM, GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, - GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, }; + GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, + GL_COMMANDS_COMPLETED_CHROMIUM, }; static const GLenum valid_read_pixel_format_table[] = {GL_ALPHA, GL_RGB, GL_RGBA, }; diff --git a/gpu/command_buffer/service/query_manager.cc b/gpu/command_buffer/service/query_manager.cc index 9f1d3a7..30c036e 100644 --- a/gpu/command_buffer/service/query_manager.cc +++ b/gpu/command_buffer/service/query_manager.cc @@ -16,6 +16,7 @@ #include "gpu/command_buffer/service/error_state.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "ui/gl/gl_fence.h" namespace gpu { namespace gles2 { @@ -389,6 +390,55 @@ void GetErrorQuery::Destroy(bool /* have_context */) { GetErrorQuery::~GetErrorQuery() { } +class CommandsCompletedQuery : public QueryManager::Query { + public: + CommandsCompletedQuery(QueryManager* manager, + GLenum target, + int32 shm_id, + uint32 shm_offset); + + // Overridden from QueryManager::Query: + virtual bool Begin() OVERRIDE; + virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE; + virtual bool Process() OVERRIDE; + virtual void Destroy(bool have_context) OVERRIDE; + + protected: + virtual ~CommandsCompletedQuery(); + + private: + scoped_ptr<gfx::GLFence> fence_; +}; + +CommandsCompletedQuery::CommandsCompletedQuery(QueryManager* manager, + GLenum target, + int32 shm_id, + uint32 shm_offset) + : Query(manager, target, shm_id, shm_offset) {} + +bool CommandsCompletedQuery::Begin() { return true; } + +bool CommandsCompletedQuery::End(base::subtle::Atomic32 submit_count) { + fence_.reset(gfx::GLFence::Create()); + DCHECK(fence_); + return AddToPendingQueue(submit_count); +} + +bool CommandsCompletedQuery::Process() { + if (fence_ && !fence_->HasCompleted()) + return true; + return MarkAsCompleted(0); +} + +void CommandsCompletedQuery::Destroy(bool have_context) { + if (have_context && !IsDeleted()) { + fence_.reset(); + MarkAsDeleted(); + } +} + +CommandsCompletedQuery::~CommandsCompletedQuery() {} + QueryManager::QueryManager( GLES2Decoder* decoder, FeatureInfo* feature_info) @@ -444,6 +494,9 @@ QueryManager::Query* QueryManager::CreateQuery( case GL_GET_ERROR_QUERY_CHROMIUM: query = new GetErrorQuery(this, target, shm_id, shm_offset); break; + case GL_COMMANDS_COMPLETED_CHROMIUM: + query = new CommandsCompletedQuery(this, target, shm_id, shm_offset); + break; default: { GLuint service_id = 0; glGenQueriesARB(1, &service_id); |