1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Tests for the QueryTracker. 6 7#include "gpu/command_buffer/client/query_tracker.h" 8 9#include <GLES2/gl2ext.h> 10#include "base/memory/scoped_ptr.h" 11#include "gpu/command_buffer/client/client_test_helper.h" 12#include "gpu/command_buffer/client/gles2_cmd_helper.h" 13#include "gpu/command_buffer/client/mapped_memory.h" 14#include "gpu/command_buffer/common/command_buffer.h" 15#include "testing/gtest/include/gtest/gtest.h" 16#include "testing/gmock/include/gmock/gmock.h" 17 18namespace gpu { 19namespace gles2 { 20 21namespace { 22void EmptyPoll() { 23} 24} 25 26class QuerySyncManagerTest : public testing::Test { 27 protected: 28 static const int32 kNumCommandEntries = 400; 29 static const int32 kCommandBufferSizeBytes = 30 kNumCommandEntries * sizeof(CommandBufferEntry); 31 32 virtual void SetUp() { 33 command_buffer_.reset(new MockClientCommandBuffer()); 34 helper_.reset(new GLES2CmdHelper(command_buffer_.get())); 35 helper_->Initialize(kCommandBufferSizeBytes); 36 mapped_memory_.reset(new MappedMemoryManager( 37 helper_.get(), base::Bind(&EmptyPoll), MappedMemoryManager::kNoLimit)); 38 sync_manager_.reset(new QuerySyncManager(mapped_memory_.get())); 39 } 40 41 virtual void TearDown() { 42 sync_manager_.reset(); 43 mapped_memory_.reset(); 44 helper_.reset(); 45 command_buffer_.reset(); 46 } 47 48 scoped_ptr<CommandBuffer> command_buffer_; 49 scoped_ptr<GLES2CmdHelper> helper_; 50 scoped_ptr<MappedMemoryManager> mapped_memory_; 51 scoped_ptr<QuerySyncManager> sync_manager_; 52}; 53 54TEST_F(QuerySyncManagerTest, Basic) { 55 QuerySyncManager::QueryInfo infos[4]; 56 memset(&infos, 0xBD, sizeof(infos)); 57 58 for (size_t ii = 0; ii < arraysize(infos); ++ii) { 59 EXPECT_TRUE(sync_manager_->Alloc(&infos[ii])); 60 EXPECT_NE(0, infos[ii].shm_id); 61 ASSERT_TRUE(infos[ii].sync != NULL); 62 EXPECT_EQ(0, infos[ii].sync->process_count); 63 EXPECT_EQ(0u, infos[ii].sync->result); 64 } 65 66 for (size_t ii = 0; ii < arraysize(infos); ++ii) { 67 sync_manager_->Free(infos[ii]); 68 } 69} 70 71TEST_F(QuerySyncManagerTest, DontFree) { 72 QuerySyncManager::QueryInfo infos[4]; 73 memset(&infos, 0xBD, sizeof(infos)); 74 75 for (size_t ii = 0; ii < arraysize(infos); ++ii) { 76 EXPECT_TRUE(sync_manager_->Alloc(&infos[ii])); 77 } 78} 79 80class QueryTrackerTest : public testing::Test { 81 protected: 82 static const int32 kNumCommandEntries = 400; 83 static const int32 kCommandBufferSizeBytes = 84 kNumCommandEntries * sizeof(CommandBufferEntry); 85 86 virtual void SetUp() { 87 command_buffer_.reset(new MockClientCommandBuffer()); 88 helper_.reset(new GLES2CmdHelper(command_buffer_.get())); 89 helper_->Initialize(kCommandBufferSizeBytes); 90 mapped_memory_.reset(new MappedMemoryManager( 91 helper_.get(), base::Bind(&EmptyPoll), MappedMemoryManager::kNoLimit)); 92 query_tracker_.reset(new QueryTracker(mapped_memory_.get())); 93 } 94 95 virtual void TearDown() { 96 query_tracker_.reset(); 97 mapped_memory_.reset(); 98 helper_.reset(); 99 command_buffer_.reset(); 100 } 101 102 QuerySync* GetSync(QueryTracker::Query* query) { 103 return query->info_.sync; 104 } 105 106 QuerySyncManager::Bucket* GetBucket(QueryTracker::Query* query) { 107 return query->info_.bucket; 108 } 109 110 uint32 GetFlushGeneration() { return helper_->flush_generation(); } 111 112 scoped_ptr<CommandBuffer> command_buffer_; 113 scoped_ptr<GLES2CmdHelper> helper_; 114 scoped_ptr<MappedMemoryManager> mapped_memory_; 115 scoped_ptr<QueryTracker> query_tracker_; 116}; 117 118TEST_F(QueryTrackerTest, Basic) { 119 const GLuint kId1 = 123; 120 const GLuint kId2 = 124; 121 122 // Check we can create a Query. 123 QueryTracker::Query* query = query_tracker_->CreateQuery( 124 kId1, GL_ANY_SAMPLES_PASSED_EXT); 125 ASSERT_TRUE(query != NULL); 126 // Check we can get the same Query. 127 EXPECT_EQ(query, query_tracker_->GetQuery(kId1)); 128 // Check we get nothing for a non-existent query. 129 EXPECT_TRUE(query_tracker_->GetQuery(kId2) == NULL); 130 // Check we can delete the query. 131 query_tracker_->RemoveQuery(kId1); 132 // Check we get nothing for a non-existent query. 133 EXPECT_TRUE(query_tracker_->GetQuery(kId1) == NULL); 134} 135 136TEST_F(QueryTrackerTest, Query) { 137 const GLuint kId1 = 123; 138 const int32 kToken = 46; 139 const uint32 kResult = 456; 140 141 // Create a Query. 142 QueryTracker::Query* query = query_tracker_->CreateQuery( 143 kId1, GL_ANY_SAMPLES_PASSED_EXT); 144 ASSERT_TRUE(query != NULL); 145 EXPECT_TRUE(query->NeverUsed()); 146 EXPECT_FALSE(query->Pending()); 147 EXPECT_EQ(0, query->token()); 148 EXPECT_EQ(0, query->submit_count()); 149 150 // Check MarkAsActive. 151 query->MarkAsActive(); 152 EXPECT_FALSE(query->NeverUsed()); 153 EXPECT_FALSE(query->Pending()); 154 EXPECT_EQ(0, query->token()); 155 EXPECT_EQ(1, query->submit_count()); 156 157 // Check MarkAsPending. 158 query->MarkAsPending(kToken); 159 EXPECT_FALSE(query->NeverUsed()); 160 EXPECT_TRUE(query->Pending()); 161 EXPECT_EQ(kToken, query->token()); 162 EXPECT_EQ(1, query->submit_count()); 163 164 // Check CheckResultsAvailable. 165 EXPECT_FALSE(query->CheckResultsAvailable(helper_.get())); 166 EXPECT_FALSE(query->NeverUsed()); 167 EXPECT_TRUE(query->Pending()); 168 169 // Flush only once if no more flushes happened between a call to 170 // EndQuery command and CheckResultsAvailable 171 // Advance put_ so flush calls in CheckResultsAvailable go through 172 // and updates flush_generation count 173 helper_->Noop(1); 174 // Set Query in pending state_ to simulate EndQuery command is called 175 query->MarkAsPending(kToken); 176 EXPECT_TRUE(query->Pending()); 177 // Store FlushGeneration count after EndQuery is called 178 uint32 gen1 = GetFlushGeneration(); 179 EXPECT_FALSE(query->CheckResultsAvailable(helper_.get())); 180 uint32 gen2 = GetFlushGeneration(); 181 EXPECT_NE(gen1, gen2); 182 // Repeated calls to CheckResultsAvailable should not flush unnecessarily 183 EXPECT_FALSE(query->CheckResultsAvailable(helper_.get())); 184 gen1 = GetFlushGeneration(); 185 EXPECT_EQ(gen1, gen2); 186 EXPECT_FALSE(query->CheckResultsAvailable(helper_.get())); 187 gen1 = GetFlushGeneration(); 188 EXPECT_EQ(gen1, gen2); 189 190 // Simulate GPU process marking it as available. 191 QuerySync* sync = GetSync(query); 192 sync->process_count = query->submit_count(); 193 sync->result = kResult; 194 195 // Check CheckResultsAvailable. 196 EXPECT_TRUE(query->CheckResultsAvailable(helper_.get())); 197 EXPECT_EQ(kResult, query->GetResult()); 198 EXPECT_FALSE(query->NeverUsed()); 199 EXPECT_FALSE(query->Pending()); 200} 201 202TEST_F(QueryTrackerTest, Remove) { 203 const GLuint kId1 = 123; 204 const int32 kToken = 46; 205 const uint32 kResult = 456; 206 207 // Create a Query. 208 QueryTracker::Query* query = query_tracker_->CreateQuery( 209 kId1, GL_ANY_SAMPLES_PASSED_EXT); 210 ASSERT_TRUE(query != NULL); 211 212 QuerySyncManager::Bucket* bucket = GetBucket(query); 213 EXPECT_EQ(1u, bucket->used_query_count); 214 215 query->MarkAsActive(); 216 query->MarkAsPending(kToken); 217 218 query_tracker_->RemoveQuery(kId1); 219 // Check we get nothing for a non-existent query. 220 EXPECT_TRUE(query_tracker_->GetQuery(kId1) == NULL); 221 222 // Check that memory was not freed. 223 EXPECT_EQ(1u, bucket->used_query_count); 224 225 // Simulate GPU process marking it as available. 226 QuerySync* sync = GetSync(query); 227 sync->process_count = query->submit_count(); 228 sync->result = kResult; 229 230 // Check FreeCompletedQueries. 231 query_tracker_->FreeCompletedQueries(); 232 EXPECT_EQ(0u, bucket->used_query_count); 233} 234 235} // namespace gles2 236} // namespace gpu 237 238 239