blob: 5d08f2e7d1441dd6b3f566e1f2a55dec304169ab (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "../client/query_tracker.h"
#include "../client/atomicops.h"
#include "../client/cmd_buffer_helper.h"
#include "../client/mapped_memory.h"
namespace gpu {
namespace gles2 {
QuerySyncManager::QuerySyncManager(MappedMemoryManager* manager)
: mapped_memory_(manager) {
GPU_DCHECK(manager);
}
QuerySyncManager::~QuerySyncManager() {
while (!buckets_.empty()) {
mapped_memory_->Free(buckets_.front());
buckets_.pop();
}
}
bool QuerySyncManager::Alloc(QuerySyncManager::QueryInfo* info) {
GPU_DCHECK(info);
if (free_queries_.empty()) {
int32 shm_id;
unsigned int shm_offset;
void* mem = mapped_memory_->Alloc(
kSyncsPerBucket * sizeof(QuerySync), &shm_id, &shm_offset);
if (!mem) {
return false;
}
QuerySync* syncs = static_cast<QuerySync*>(mem);
buckets_.push(syncs);
for (size_t ii = 0; ii < kSyncsPerBucket; ++ii) {
free_queries_.push(QueryInfo(shm_id, shm_offset, syncs));
++syncs;
shm_offset += sizeof(*syncs);
}
}
*info = free_queries_.front();
info->sync->Reset();
free_queries_.pop();
return true;
}
void QuerySyncManager::Free(const QuerySyncManager::QueryInfo& info) {
free_queries_.push(info);
}
bool QueryTracker::Query::CheckResultsAvailable(
CommandBufferHelper* helper) {
if (Pending()) {
if (info_.sync->process_count == submit_count_) {
// Need a MemoryBarrier here so that sync->result read after
// sync->process_count.
gpu::MemoryBarrier();
result_ = info_.sync->result;
state_ = kComplete;
} else {
if (!flushed_) {
// TODO(gman): We could reduce the number of flushes by having a
// flush count, recording that count at the time we insert the
// EndQuery command and then only flushing here if we've have not
// passed that count yet.
flushed_ = true;
helper->Flush();
} else {
// Insert no-ops so that eventually the GPU process will see more work.
helper->Noop(1);
}
}
}
return state_ == kComplete;
}
uint32 QueryTracker::Query::GetResult() const {
GPU_DCHECK(state_ == kComplete || state_ == kUninitialized);
return result_;
}
QueryTracker::QueryTracker(MappedMemoryManager* manager)
: query_sync_manager_(manager) {
}
QueryTracker::~QueryTracker() {
queries_.clear();
}
QueryTracker::Query* QueryTracker::CreateQuery(GLuint id, GLenum target) {
GPU_DCHECK_NE(0u, id);
QuerySyncManager::QueryInfo info;
if (!query_sync_manager_.Alloc(&info)) {
return NULL;
}
Query* query = new Query(id, target, info);
std::pair<QueryMap::iterator, bool> result =
queries_.insert(std::make_pair(id, query));
GPU_DCHECK(result.second);
return query;
}
QueryTracker::Query* QueryTracker::GetQuery(
GLuint client_id) {
QueryMap::iterator it = queries_.find(client_id);
return it != queries_.end() ? it->second : NULL;
}
void QueryTracker::RemoveQuery(GLuint client_id) {
QueryMap::iterator it = queries_.find(client_id);
if (it != queries_.end()) {
Query* query = it->second;
GPU_DCHECK(!query->Pending());
query_sync_manager_.Free(query->info_);
queries_.erase(it);
delete query;
}
}
} // namespace gles2
} // namespace gpu
|