Home | History | Annotate | Download | only in client
      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 
     18 namespace gpu {
     19 namespace gles2 {
     20 
     21 namespace {
     22 void EmptyPoll() {
     23 }
     24 }
     25 
     26 class 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 
     54 TEST_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 
     71 TEST_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 
     80 class 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 
    118 TEST_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 
    136 TEST_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 
    202 TEST_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