137 lines
3.6 KiB
JavaScript
137 lines
3.6 KiB
JavaScript
var GL_QUERY_RESULT_EXT = 0x8866
|
|
var GL_QUERY_RESULT_AVAILABLE_EXT = 0x8867
|
|
var GL_TIME_ELAPSED_EXT = 0x88BF
|
|
|
|
module.exports = function (gl, extensions) {
|
|
if (!extensions.ext_disjoint_timer_query) {
|
|
return null
|
|
}
|
|
|
|
// QUERY POOL BEGIN
|
|
var queryPool = []
|
|
function allocQuery () {
|
|
return queryPool.pop() || extensions.ext_disjoint_timer_query.createQueryEXT()
|
|
}
|
|
function freeQuery (query) {
|
|
queryPool.push(query)
|
|
}
|
|
// QUERY POOL END
|
|
|
|
var pendingQueries = []
|
|
function beginQuery (stats) {
|
|
var query = allocQuery()
|
|
extensions.ext_disjoint_timer_query.beginQueryEXT(GL_TIME_ELAPSED_EXT, query)
|
|
pendingQueries.push(query)
|
|
pushScopeStats(pendingQueries.length - 1, pendingQueries.length, stats)
|
|
}
|
|
|
|
function endQuery () {
|
|
extensions.ext_disjoint_timer_query.endQueryEXT(GL_TIME_ELAPSED_EXT)
|
|
}
|
|
|
|
//
|
|
// Pending stats pool.
|
|
//
|
|
function PendingStats () {
|
|
this.startQueryIndex = -1
|
|
this.endQueryIndex = -1
|
|
this.sum = 0
|
|
this.stats = null
|
|
}
|
|
var pendingStatsPool = []
|
|
function allocPendingStats () {
|
|
return pendingStatsPool.pop() || new PendingStats()
|
|
}
|
|
function freePendingStats (pendingStats) {
|
|
pendingStatsPool.push(pendingStats)
|
|
}
|
|
// Pending stats pool end
|
|
|
|
var pendingStats = []
|
|
function pushScopeStats (start, end, stats) {
|
|
var ps = allocPendingStats()
|
|
ps.startQueryIndex = start
|
|
ps.endQueryIndex = end
|
|
ps.sum = 0
|
|
ps.stats = stats
|
|
pendingStats.push(ps)
|
|
}
|
|
|
|
// we should call this at the beginning of the frame,
|
|
// in order to update gpuTime
|
|
var timeSum = []
|
|
var queryPtr = []
|
|
function update () {
|
|
var ptr, i
|
|
|
|
var n = pendingQueries.length
|
|
if (n === 0) {
|
|
return
|
|
}
|
|
|
|
// Reserve space
|
|
queryPtr.length = Math.max(queryPtr.length, n + 1)
|
|
timeSum.length = Math.max(timeSum.length, n + 1)
|
|
timeSum[0] = 0
|
|
queryPtr[0] = 0
|
|
|
|
// Update all pending timer queries
|
|
var queryTime = 0
|
|
ptr = 0
|
|
for (i = 0; i < pendingQueries.length; ++i) {
|
|
var query = pendingQueries[i]
|
|
if (extensions.ext_disjoint_timer_query.getQueryObjectEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT)) {
|
|
queryTime += extensions.ext_disjoint_timer_query.getQueryObjectEXT(query, GL_QUERY_RESULT_EXT)
|
|
freeQuery(query)
|
|
} else {
|
|
pendingQueries[ptr++] = query
|
|
}
|
|
timeSum[i + 1] = queryTime
|
|
queryPtr[i + 1] = ptr
|
|
}
|
|
pendingQueries.length = ptr
|
|
|
|
// Update all pending stat queries
|
|
ptr = 0
|
|
for (i = 0; i < pendingStats.length; ++i) {
|
|
var stats = pendingStats[i]
|
|
var start = stats.startQueryIndex
|
|
var end = stats.endQueryIndex
|
|
stats.sum += timeSum[end] - timeSum[start]
|
|
var startPtr = queryPtr[start]
|
|
var endPtr = queryPtr[end]
|
|
if (endPtr === startPtr) {
|
|
stats.stats.gpuTime += stats.sum / 1e6
|
|
freePendingStats(stats)
|
|
} else {
|
|
stats.startQueryIndex = startPtr
|
|
stats.endQueryIndex = endPtr
|
|
pendingStats[ptr++] = stats
|
|
}
|
|
}
|
|
pendingStats.length = ptr
|
|
}
|
|
|
|
return {
|
|
beginQuery: beginQuery,
|
|
endQuery: endQuery,
|
|
pushScopeStats: pushScopeStats,
|
|
update: update,
|
|
getNumPendingQueries: function () {
|
|
return pendingQueries.length
|
|
},
|
|
clear: function () {
|
|
queryPool.push.apply(queryPool, pendingQueries)
|
|
for (var i = 0; i < queryPool.length; i++) {
|
|
extensions.ext_disjoint_timer_query.deleteQueryEXT(queryPool[i])
|
|
}
|
|
pendingQueries.length = 0
|
|
queryPool.length = 0
|
|
},
|
|
restore: function () {
|
|
pendingQueries.length = 0
|
|
queryPool.length = 0
|
|
}
|
|
}
|
|
}
|