diff options
author | dyen <dyen@chromium.org> | 2016-01-05 16:50:16 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-06 00:52:09 +0000 |
commit | 882d69d97b5c43b7579bc610722dbadd328ac63e (patch) | |
tree | 5fb8f5f9fcf3e4d81600f90579fcbf9e274714fc | |
parent | 7fbe484c9fff54d9fd536a3a762b2bcfa9ad782e (diff) | |
download | chromium_src-882d69d97b5c43b7579bc610722dbadd328ac63e.zip chromium_src-882d69d97b5c43b7579bc610722dbadd328ac63e.tar.gz chromium_src-882d69d97b5c43b7579bc610722dbadd328ac63e.tar.bz2 |
Verify resource provider sync tokens before sending to parent.
R=piman@chromium.org
BUG=514815
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
Review URL: https://codereview.chromium.org/1479673003
Cr-Commit-Position: refs/heads/master@{#367727}
-rw-r--r-- | cc/resources/resource_provider.cc | 26 | ||||
-rw-r--r-- | cc/resources/resource_provider_unittest.cc | 110 | ||||
-rw-r--r-- | cc/test/test_gles2_interface.cc | 19 | ||||
-rw-r--r-- | cc/test/test_gles2_interface.h | 6 | ||||
-rw-r--r-- | cc/test/test_web_graphics_context_3d.cc | 28 | ||||
-rw-r--r-- | cc/test/test_web_graphics_context_3d.h | 7 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.cc | 32 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_unittest.cc | 70 |
8 files changed, 239 insertions, 59 deletions
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index c6e5c91..f1a4cf2 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc @@ -1140,6 +1140,9 @@ void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources, DCHECK(thread_checker_.CalledOnValidThread()); GLES2Interface* gl = ContextGL(); bool need_sync_token = false; + + gpu::SyncToken new_sync_token; + std::vector<GLbyte*> unverified_sync_tokens; for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) { @@ -1147,17 +1150,36 @@ void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources, TransferResource(gl, *it, &resource); need_sync_token |= (!resource.mailbox_holder.sync_token.HasData() && !resource.is_software); + + if (resource.mailbox_holder.sync_token.HasData() && + !resource.mailbox_holder.sync_token.verified_flush()) { + unverified_sync_tokens.push_back( + resource.mailbox_holder.sync_token.GetData()); + } + ++resources_.find(*it)->second.exported_count; list->push_back(resource); } + if (need_sync_token && output_surface_->capabilities().delegated_sync_points_required) { - gpu::SyncToken sync_token(gl->InsertSyncPointCHROMIUM()); + const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); + gl->OrderingBarrierCHROMIUM(); + gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, new_sync_token.GetData()); + unverified_sync_tokens.push_back(new_sync_token.GetData()); + } + + if (!unverified_sync_tokens.empty()) { + gl->VerifySyncTokensCHROMIUM(unverified_sync_tokens.data(), + unverified_sync_tokens.size()); + } + + if (new_sync_token.HasData()) { for (TransferableResourceArray::iterator it = list->begin(); it != list->end(); ++it) { if (!it->mailbox_holder.sync_token.HasData()) - it->mailbox_holder.sync_token = sync_token; + it->mailbox_holder.sync_token = new_sync_token; } } } diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc index 3374e85..1a0e685 100644 --- a/cc/resources/resource_provider_unittest.cc +++ b/cc/resources/resource_provider_unittest.cc @@ -39,7 +39,6 @@ using testing::Mock; using testing::NiceMock; using testing::Return; -using testing::SetArgPointee; using testing::StrictMock; using testing::_; @@ -104,7 +103,6 @@ class TextureStateTrackingContext : public TestWebGraphicsContext3D { MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture)); MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param)); MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token)); - MOCK_METHOD0(insertSyncPoint, GLuint(void)); MOCK_METHOD3(produceTextureDirectCHROMIUM, void(GLuint texture, GLenum target, const GLbyte* mailbox)); MOCK_METHOD2(createAndConsumeTextureCHROMIUM, @@ -116,7 +114,21 @@ class TextureStateTrackingContext : public TestWebGraphicsContext3D { base::AutoLock lock(namespace_->lock); return namespace_->next_texture_id++; } + void RetireTextureId(GLuint) override {} + + GLuint64 insertFenceSync() override { return next_fence_sync_++; } + + void genSyncToken(GLuint64 fence_sync, GLbyte* sync_token) override { + gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, 0, + 0x123, fence_sync); + sync_token_data.SetVerifyFlush(); + memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); + } + + GLuint64 GetNextFenceSync() const { return next_fence_sync_; } + + GLuint64 next_fence_sync_ = 1; }; // Shared data between multiple ResourceProviderContext. This contains mailbox @@ -127,7 +139,7 @@ class ContextSharedData { return make_scoped_ptr(new ContextSharedData()); } - uint32_t InsertSyncPoint() { return next_sync_point_++; } + uint32_t InsertFenceSync() { return next_fence_sync_++; } void GenMailbox(GLbyte* mailbox) { memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM); @@ -165,9 +177,9 @@ class ContextSharedData { } private: - ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {} + ContextSharedData() : next_fence_sync_(1), next_mailbox_(1) {} - uint32_t next_sync_point_; + uint64_t next_fence_sync_; unsigned next_mailbox_; typedef base::hash_map<unsigned, scoped_refptr<TestTexture>> TextureMap; TextureMap textures_; @@ -182,19 +194,40 @@ class ResourceProviderContext : public TestWebGraphicsContext3D { } GLuint insertSyncPoint() override { - uint32_t sync_point = shared_data_->InsertSyncPoint(); + const uint32_t sync_point = + static_cast<uint32_t>(shared_data_->InsertFenceSync()); + gpu::SyncToken sync_token_data(sync_point); + // Commit the produceTextureCHROMIUM calls at this point, so that // they're associated with the sync point. for (const scoped_ptr<PendingProduceTexture>& pending_texture : pending_produce_textures_) { - shared_data_->ProduceTexture(pending_texture->mailbox, - gpu::SyncToken(sync_point), + shared_data_->ProduceTexture(pending_texture->mailbox, sync_token_data, pending_texture->texture); } pending_produce_textures_.clear(); return sync_point; } + GLuint64 insertFenceSync() override { + return shared_data_->InsertFenceSync(); + } + + void genSyncToken(GLuint64 fence_sync, GLbyte* sync_token) override { + gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, 0, + 0x123, fence_sync); + sync_token_data.SetVerifyFlush(); + // Commit the produceTextureCHROMIUM calls at this point, so that + // they're associated with the sync point. + for (const scoped_ptr<PendingProduceTexture>& pending_texture : + pending_produce_textures_) { + shared_data_->ProduceTexture(pending_texture->mailbox, sync_token_data, + pending_texture->texture); + } + pending_produce_textures_.clear(); + memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); + } + void waitSyncToken(const GLbyte* sync_token) override { gpu::SyncToken sync_token_data; if (sync_token) @@ -280,7 +313,7 @@ class ResourceProviderContext : public TestWebGraphicsContext3D { GLenum target, const GLbyte* mailbox) override { // Delay moving the texture into the mailbox until the next - // InsertSyncPoint, so that it is not visible to other contexts that + // sync token, so that it is not visible to other contexts that // haven't waited on that sync point. scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture); memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox)); @@ -477,7 +510,8 @@ class ResourceProviderTest child_context_->genMailboxCHROMIUM(gpu_mailbox.name); child_context_->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, gpu_mailbox.name); - *sync_token = gpu::SyncToken(child_context_->insertSyncPoint()); + child_context_->genSyncToken(child_context_->insertFenceSync(), + sync_token->GetData()); EXPECT_TRUE(sync_token->HasData()); scoped_ptr<SharedBitmap> shared_bitmap; @@ -633,7 +667,10 @@ TEST_P(ResourceProviderTest, TransferGLResources) { child_context_->genMailboxCHROMIUM(external_mailbox.name); child_context_->produceTextureDirectCHROMIUM( external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name); - const gpu::SyncToken external_sync_token(child_context_->insertSyncPoint()); + gpu::SyncToken external_sync_token; + child_context_->genSyncToken(child_context_->insertFenceSync(), + external_sync_token.GetData()); + EXPECT_TRUE(external_sync_token.HasData()); ResourceId id4 = child_resource_provider_->CreateResourceFromTextureMailbox( TextureMailbox(external_mailbox, external_sync_token, GL_TEXTURE_EXTERNAL_OES), @@ -889,7 +926,10 @@ TEST_P(ResourceProviderTestNoSyncToken, TransferGLResources) { child_context_->genMailboxCHROMIUM(external_mailbox.name); child_context_->produceTextureDirectCHROMIUM( external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name); - const gpu::SyncToken external_sync_token(child_context_->insertSyncPoint()); + gpu::SyncToken external_sync_token; + child_context_->genSyncToken(child_context_->insertFenceSync(), + external_sync_token.GetData()); + EXPECT_TRUE(external_sync_token.HasData()); ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox( TextureMailbox(external_mailbox, external_sync_token, GL_TEXTURE_EXTERNAL_OES), @@ -1961,7 +2001,6 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { EXPECT_CALL(*child_context, produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _)); - EXPECT_CALL(*child_context, insertSyncPoint()); child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list); Mock::VerifyAndClearExpectations(child_context); @@ -2019,7 +2058,6 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { // Transfer resources back from the parent to the child. Set no resources // as being in use. ResourceProvider::ResourceIdSet no_resources; - EXPECT_CALL(*parent_context, insertSyncPoint()); parent_resource_provider->DeclareUsedResourcesFromChild(child_id, no_resources); Mock::VerifyAndClearExpectations(parent_context); @@ -2059,7 +2097,9 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) { gpu::Mailbox mailbox; context()->genMailboxCHROMIUM(mailbox.name); context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name); - gpu::SyncToken sync_token(context()->insertSyncPoint()); + gpu::SyncToken sync_token; + context()->genSyncToken(context()->insertFenceSync(), sync_token.GetData()); + EXPECT_TRUE(sync_token.HasData()); // All the logic below assumes that the sync token releases are all positive. EXPECT_LT(0u, sync_token.release_count()); @@ -2101,8 +2141,9 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) { context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D, mailbox.name); context()->deleteTexture(other_texture); - list[0].mailbox_holder.sync_token = - gpu::SyncToken(context()->insertSyncPoint()); + context()->genSyncToken(context()->insertFenceSync(), + list[0].mailbox_holder.sync_token.GetData()); + EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); // Receive the resource, then delete it, expect the sync points to be // consistent. @@ -2155,9 +2196,9 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) { context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D, mailbox.name); context()->deleteTexture(other_texture); - list[0].mailbox_holder.sync_token = - gpu::SyncToken(context()->insertSyncPoint()); - EXPECT_LT(0u, list[0].mailbox_holder.sync_token.release_count()); + context()->genSyncToken(context()->insertFenceSync(), + list[0].mailbox_holder.sync_token.GetData()); + EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); // Delete the resource, which shouldn't do anything. resource_provider_->DeleteResource(resource); @@ -2490,7 +2531,8 @@ TEST_P(ResourceProviderTest, LostContext) { gpu::Mailbox mailbox; context()->genMailboxCHROMIUM(mailbox.name); context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name); - gpu::SyncToken sync_token(context()->insertSyncPoint()); + gpu::SyncToken sync_token; + context()->genSyncToken(context()->insertFenceSync(), sync_token.GetData()); EXPECT_TRUE(sync_token.HasData()); @@ -2810,12 +2852,13 @@ class ResourceProviderTestTextureMailboxGLFilters use_image_texture_targets_)); unsigned texture_id = 1; - gpu::SyncToken sync_token(30); + gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, 0x12, + 0x34); unsigned target = GL_TEXTURE_2D; + const GLuint64 current_fence_sync = context->GetNextFenceSync(); EXPECT_CALL(*context, bindTexture(_, _)).Times(0); EXPECT_CALL(*context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*context, insertSyncPoint()).Times(0); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); @@ -2835,6 +2878,7 @@ class ResourceProviderTestTextureMailboxGLFilters ResourceId id = resource_provider->CreateResourceFromTextureMailbox( mailbox, std::move(callback)); EXPECT_NE(0u, id); + EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); Mock::VerifyAndClearExpectations(context); @@ -2848,7 +2892,6 @@ class ResourceProviderTestTextureMailboxGLFilters .WillOnce(Return(texture_id)); EXPECT_CALL(*context, bindTexture(target, texture_id)); - EXPECT_CALL(*context, insertSyncPoint()).Times(0); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); // The sampler will reset these if |mailbox_nearest_neighbor| does not @@ -2863,11 +2906,11 @@ class ResourceProviderTestTextureMailboxGLFilters ResourceProvider::ScopedSamplerGL lock( resource_provider.get(), id, sampler_filter); Mock::VerifyAndClearExpectations(context); + EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); // When done with it, a sync point should be inserted, but no produce is // necessary. EXPECT_CALL(*context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*context, insertSyncPoint()); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, waitSyncToken(_)).Times(0); @@ -2875,7 +2918,7 @@ class ResourceProviderTestTextureMailboxGLFilters } resource_provider->DeleteResource(id); - EXPECT_FALSE(release_sync_token.HasData()); + EXPECT_TRUE(release_sync_token.HasData()); EXPECT_FALSE(lost_resource); EXPECT_EQ(main_thread_task_runner, mailbox_task_runner); } @@ -2952,12 +2995,12 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { gpu_memory_buffer_manager_.get(), NULL, 0, 1, use_gpu_memory_buffer_resources_, use_image_texture_targets_)); - gpu::SyncToken sync_token(30); + gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, 0x12, 0x34); + const GLuint64 current_fence_sync = context->GetNextFenceSync(); unsigned target = GL_TEXTURE_EXTERNAL_OES; EXPECT_CALL(*context, bindTexture(_, _)).Times(0); EXPECT_CALL(*context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*context, insertSyncPoint()).Times(0); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); @@ -2971,6 +3014,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { ResourceId id = resource_provider->CreateResourceFromTextureMailbox( mailbox, std::move(callback)); EXPECT_NE(0u, id); + EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); Mock::VerifyAndClearExpectations(context); @@ -2985,7 +3029,6 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _)) .WillOnce(Return(texture_id)); - EXPECT_CALL(*context, insertSyncPoint()).Times(0); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id); @@ -2994,7 +3037,6 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { // When done with it, a sync point should be inserted, but no produce is // necessary. EXPECT_CALL(*context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*context, insertSyncPoint()); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, waitSyncToken(_)).Times(0); @@ -3022,12 +3064,12 @@ TEST_P(ResourceProviderTest, gpu_memory_buffer_manager_.get(), NULL, 0, 1, use_gpu_memory_buffer_resources_, use_image_texture_targets_)); - gpu::SyncToken sync_token(30); + gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, 0x12, 0x34); + const GLuint64 current_fence_sync = context->GetNextFenceSync(); unsigned target = GL_TEXTURE_2D; EXPECT_CALL(*context, bindTexture(_, _)).Times(0); EXPECT_CALL(*context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*context, insertSyncPoint()).Times(0); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); @@ -3041,6 +3083,7 @@ TEST_P(ResourceProviderTest, ResourceId id = resource_provider->CreateResourceFromTextureMailbox( mailbox, std::move(callback)); EXPECT_NE(0u, id); + EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); Mock::VerifyAndClearExpectations(context); @@ -3077,11 +3120,11 @@ TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncTokenIfNeeded_NoSyncToken) { use_gpu_memory_buffer_resources_, use_image_texture_targets_)); gpu::SyncToken sync_token; + const GLuint64 current_fence_sync = context->GetNextFenceSync(); unsigned target = GL_TEXTURE_2D; EXPECT_CALL(*context, bindTexture(_, _)).Times(0); EXPECT_CALL(*context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*context, insertSyncPoint()).Times(0); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); @@ -3095,6 +3138,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncTokenIfNeeded_NoSyncToken) { ResourceId id = resource_provider->CreateResourceFromTextureMailbox( mailbox, std::move(callback)); EXPECT_NE(0u, id); + EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); Mock::VerifyAndClearExpectations(context); diff --git a/cc/test/test_gles2_interface.cc b/cc/test/test_gles2_interface.cc index 2781712..97766fb 100644 --- a/cc/test/test_gles2_interface.cc +++ b/cc/test/test_gles2_interface.cc @@ -327,6 +327,25 @@ GLuint TestGLES2Interface::InsertSyncPointCHROMIUM() { return test_context_->insertSyncPoint(); } +GLuint64 TestGLES2Interface::InsertFenceSyncCHROMIUM() { + return test_context_->insertFenceSync(); +} + +void TestGLES2Interface::GenSyncTokenCHROMIUM(GLuint64 fence_sync, + GLbyte* sync_token) { + test_context_->genSyncToken(fence_sync, sync_token); +} + +void TestGLES2Interface::GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, + GLbyte* sync_token) { + test_context_->genSyncToken(fence_sync, sync_token); +} + +void TestGLES2Interface::VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, + GLsizei count) { + test_context_->verifySyncTokens(sync_tokens, count); +} + void TestGLES2Interface::WaitSyncTokenCHROMIUM(const GLbyte* sync_token) { test_context_->waitSyncToken(sync_token); } diff --git a/cc/test/test_gles2_interface.h b/cc/test/test_gles2_interface.h index 0914810..fe4f16f 100644 --- a/cc/test/test_gles2_interface.h +++ b/cc/test/test_gles2_interface.h @@ -138,7 +138,11 @@ class TestGLES2Interface : public gpu::gles2::GLES2InterfaceStub { GLenum usage) override; GLuint InsertSyncPointCHROMIUM() override; - + GLuint64 InsertFenceSyncCHROMIUM() override; + void GenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token) override; + void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, + GLbyte* sync_token) override; + void VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, GLsizei count) override; void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) override; void BeginQueryEXT(GLenum target, GLuint id) override; diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc index 96b11b4..8e4df91 100644 --- a/cc/test/test_web_graphics_context_3d.cc +++ b/cc/test/test_web_graphics_context_3d.cc @@ -69,7 +69,7 @@ TestWebGraphicsContext3D::TestWebGraphicsContext3D() scale_factor_(-1.f), test_support_(NULL), last_update_type_(NO_UPDATE), - next_insert_sync_point_(1), + next_insert_fence_sync_(1), unpack_alignment_(4), bound_buffer_(0), weak_ptr_factory_(this) { @@ -649,8 +649,20 @@ GLuint TestWebGraphicsContext3D::createGpuMemoryBufferImageCHROMIUM( return image_id; } -unsigned TestWebGraphicsContext3D::insertSyncPoint() { - return next_insert_sync_point_++; +GLuint TestWebGraphicsContext3D::insertSyncPoint() { + return static_cast<GLuint>(next_insert_fence_sync_++); +} + +GLuint64 TestWebGraphicsContext3D::insertFenceSync() { + return next_insert_fence_sync_++; +} + +void TestWebGraphicsContext3D::genSyncToken(GLuint64 fence_sync, + GLbyte* sync_token) { + gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, 0, 0, + fence_sync); + sync_token_data.SetVerifyFlush(); + memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); } void TestWebGraphicsContext3D::waitSyncToken(const GLbyte* sync_token) { @@ -662,6 +674,16 @@ void TestWebGraphicsContext3D::waitSyncToken(const GLbyte* sync_token) { } } +void TestWebGraphicsContext3D::verifySyncTokens(GLbyte** sync_tokens, + GLsizei count) { + for (GLsizei i = 0; i < count; ++i) { + gpu::SyncToken sync_token_data; + memcpy(sync_token_data.GetData(), sync_tokens[i], sizeof(sync_token_data)); + sync_token_data.SetVerifyFlush(); + memcpy(sync_tokens[i], &sync_token_data, sizeof(sync_token_data)); + } +} + size_t TestWebGraphicsContext3D::NumTextures() const { base::AutoLock lock(namespace_->lock); return namespace_->textures.Size(); diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h index 08447f7..fba2b8d 100644 --- a/cc/test/test_web_graphics_context_3d.h +++ b/cc/test/test_web_graphics_context_3d.h @@ -275,8 +275,11 @@ class TestWebGraphicsContext3D { GLuint io_surface_id, GLuint plane) {} - virtual unsigned insertSyncPoint(); + virtual GLuint insertSyncPoint(); + virtual GLuint64 insertFenceSync(); + virtual void genSyncToken(GLuint64 fence_sync, GLbyte* sync_token); virtual void waitSyncToken(const GLbyte* sync_token); + virtual void verifySyncTokens(GLbyte** sync_tokens, GLsizei count); const gpu::SyncToken& last_waited_sync_token() const { return last_waited_sync_token_; @@ -482,7 +485,7 @@ class TestWebGraphicsContext3D { TestContextSupport* test_support_; gfx::Rect update_rect_; UpdateType last_update_type_; - unsigned next_insert_sync_point_; + GLuint64 next_insert_fence_sync_; gpu::SyncToken last_waited_sync_token_; int unpack_alignment_; diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 96d08e1..556eea7 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -5589,7 +5589,7 @@ void GLES2Implementation::GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, void GLES2Implementation::VerifySyncTokensCHROMIUM(GLbyte **sync_tokens, GLsizei count) { - bool sync_tokens_verified = false; + bool requires_synchronization = false; for (GLsizei i = 0; i < count; ++i) { if (sync_tokens[i]) { SyncToken sync_token; @@ -5601,18 +5601,26 @@ void GLES2Implementation::VerifySyncTokensCHROMIUM(GLbyte **sync_tokens, "Cannot verify sync token using this context."); return; } - if (!sync_tokens_verified) { - // Insert a fence sync here and ensure it is received immediately. - // This will require a flush but simplifies things a bit because - // unverified sync tokens only need an ordering barrier. - const uint64_t release = gpu_control_->GenerateFenceSyncRelease(); - FlushHelper(); - const bool verified = gpu_control_->IsFenceSyncFlushReceived(release); - DCHECK(verified); - - sync_tokens_verified = true; - } + requires_synchronization = true; + } + } + } + + // This step must be done after all unverified tokens have finished processing + // CanWaitUnverifiedSyncToken(), command buffers use that to do any necessary + // flushes. + if (requires_synchronization) { + // Make sure we have no pending ordering barriers by flushing now. + FlushHelper(); + // Ensure all the fence syncs are visible on GPU service. + gpu_control_->EnsureWorkVisible(); + + // We can automatically mark everything as verified now. + for (GLsizei i = 0; i < count; ++i) { + SyncToken sync_token; + memcpy(&sync_token, sync_tokens[i], sizeof(sync_token)); + if (!sync_token.verified_flush()) { sync_token.SetVerifyFlush(); memcpy(sync_tokens[i], &sync_token, sizeof(sync_token)); } diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 732107b..e408610 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -35,6 +35,7 @@ using testing::DoAll; using testing::InSequence; using testing::Invoke; using testing::Mock; +using testing::Pointee; using testing::Sequence; using testing::StrictMock; using testing::Truly; @@ -3881,14 +3882,10 @@ TEST_F(GLES2ImplementationTest, VerifySyncTokensCHROMIUM) { EXPECT_FALSE(sync_token.verified_flush()); ClearCommands(); - const GLuint64 kVerifyFenceSync = 234u; EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(_)) .WillOnce(testing::Return(true)); - EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()) - .WillOnce(testing::Return(kVerifyFenceSync)); - EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(kVerifyFenceSync)) - .WillOnce(testing::Return(true)); - gl_->VerifySyncTokensCHROMIUM(sync_token_datas, 1); + EXPECT_CALL(*gpu_control_, EnsureWorkVisible()); + gl_->VerifySyncTokensCHROMIUM(sync_token_datas, arraysize(sync_token_datas)); EXPECT_TRUE(NoCommandsWritten()); EXPECT_EQ(GL_NO_ERROR, CheckError()); @@ -3898,6 +3895,67 @@ TEST_F(GLES2ImplementationTest, VerifySyncTokensCHROMIUM) { EXPECT_TRUE(sync_token.verified_flush()); } +TEST_F(GLES2ImplementationTest, VerifySyncTokensCHROMIUM_Sequence) { + // To verify sync tokens, the sync tokens must all be verified after + // CanWaitUnverifiedSyncTokens() are called. This test ensures the right + // sequence. + ExpectedMemoryInfo result = + GetExpectedResultMemory(sizeof(cmds::GetError::Result)); + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillRepeatedly(SetMemory(result.ptr, GLuint(GL_NO_ERROR))) + .RetiresOnSaturation(); + + const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO; + const GLuint64 kCommandBufferId = 234u; + const GLuint64 kFenceSync1 = 123u; + const GLuint64 kFenceSync2 = 234u; + gpu::SyncToken sync_token1; + gpu::SyncToken sync_token2; + GLbyte* sync_token_datas[] = { sync_token1.GetData(), sync_token2.GetData() }; + + EXPECT_CALL(*gpu_control_, GetNamespaceID()) + .WillRepeatedly(Return(kNamespaceId)); + EXPECT_CALL(*gpu_control_, GetCommandBufferID()) + .WillRepeatedly(Return(kCommandBufferId)); + EXPECT_CALL(*gpu_control_, GetExtraCommandBufferData()) + .WillRepeatedly(Return(0)); + + // Generate sync token 1. + EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync1)) + .WillOnce(Return(true)); + EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync1)) + .WillOnce(Return(true)); + gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync1, sync_token1.GetData()); + ASSERT_TRUE(sync_token1.HasData()); + ASSERT_FALSE(sync_token1.verified_flush()); + + // Generate sync token 2. + EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync2)) + .WillOnce(Return(true)); + EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync2)) + .WillOnce(Return(true)); + gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync2, sync_token2.GetData()); + ASSERT_TRUE(sync_token2.HasData()); + ASSERT_FALSE(sync_token2.verified_flush()); + + // Ensure proper sequence of checking and validating. + Sequence sequence; + EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(Pointee(sync_token1))) + .InSequence(sequence) + .WillOnce(Return(true)); + EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(Pointee(sync_token2))) + .InSequence(sequence) + .WillOnce(Return(true)); + EXPECT_CALL(*gpu_control_, EnsureWorkVisible()) + .InSequence(sequence); + gl_->VerifySyncTokensCHROMIUM(sync_token_datas, arraysize(sync_token_datas)); + EXPECT_TRUE(NoCommandsWritten()); + EXPECT_EQ(GL_NO_ERROR, CheckError()); + + EXPECT_TRUE(sync_token1.verified_flush()); + EXPECT_TRUE(sync_token2.verified_flush()); +} + TEST_F(GLES2ImplementationTest, WaitSyncTokenCHROMIUM) { const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO; const GLuint64 kCommandBufferId = 234u; |