EXT_disjoint_timer_query possible bug in Chrome

280 views
Skip to first unread message

Nick Brancaccio

unread,
Jun 1, 2016, 9:13:33 PM6/1/16
to WebGL Dev List
Anyone having issues with EXT_disjoint_timer_query in the latest stable release of Chrome 

I just updated chrome to the latest (51.0.2704.79) from (50.0.2661.102), which seems to have broken a chunk of previously working code that used disjoint timer queries. I tested in Canary and have the same issue.

The pattern is:

var ext = gl.getExtension("EXT_disjoint_timer_query");

var queryStart = ext.createQueryEXT();
var queryEnd = ext.createQueryEXT();

ext.queryCounterEXT(queryStart, ext.TIMESTAMP_EXT);
// ... execute some webGL calls
ext.queryCounterEXT(queryEnd, ext.TIMESTAMP_EXT);

// ... a few frames later:
var queryAvailableStart = ext.getQueryObjectEXT(queryStart, ext.QUERY_RESULT_AVAILABLE_EXT);
var queryAvailableEnd = ext.getQueryObjectEXT(queryEnd, ext.QUERY_RESULT_AVAILABLE_EXT);
var disjoint = gl.getParameter(this.queryExtension.GPU_DISJOINT_EXT);

if (queryAvailableStart && queryAvailableEnd && !disjoint) {
    var timeStart = ext.getQueryObjectEXT(queryStart, ext.QUERY_RESULT_EXT);
    var timeEnd = ext.getQueryObjectEXT(queryEnd, ext.QUERY_RESULT_EXT);

    // Convert from nanoseconds to milliseconds.
    var ellapsedTime = 1e-6 * (timeEnd - timeStart);
}

The new / strange behavior is that timeStart and timeEnd both evaluate to 0, making ellapsedTime 0

Anyone else seeing this behavior?
Thanks,
-Nick

Kenneth Russell

unread,
Jun 1, 2016, 9:22:22 PM6/1/16
to WebGL Dev List
Apologies, but timestamp queries turned out to be non-portable and they were disabled in Chrome on all platforms. Please use elapsed time queries instead.

-Ken


--
You received this message because you are subscribed to the Google Groups "WebGL Dev List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webgl-dev-lis...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Nick Brancaccio

unread,
Jun 1, 2016, 9:51:18 PM6/1/16
to WebGL Dev List
Ah gotcha, thanks for the clarification Ken

My current implementation (with timestamp queries) relies on nested queries. However, unlike startQueryEXT, endQueryEXT doesn't take a query as an arg (ie: ext.endQueryEXT(ext.TIME_ELAPSED_EXT)), so I'm unsure how to specify which query to end.

Can the following pattern be achieved with elapsed time queries?

startQueryA
    startQueryB
        startQueryC
        endQUeryC
    endQueryB
endQueryA

Thanks,
-Nick

Nick Brancaccio

unread,
Jun 1, 2016, 10:24:03 PM6/1/16
to WebGL Dev List
I should also point out that:
 1.) The nested approach above isn't strictly necessary, more of a convenience to allow timer injection anywhere, without worrying about sequencing.
 2.) I switched to elapsedtime queries and the results are much more stable, so thanks for that :)

Kenneth Russell

unread,
Jun 2, 2016, 6:02:27 PM6/2/16
to WebGL Dev List
On Wed, Jun 1, 2016 at 6:51 PM, Nick Brancaccio <ni...@floored.com> wrote:
Ah gotcha, thanks for the clarification Ken

My current implementation (with timestamp queries) relies on nested queries. However, unlike startQueryEXT, endQueryEXT doesn't take a query as an arg (ie: ext.endQueryEXT(ext.TIME_ELAPSED_EXT)), so I'm unsure how to specify which query to end.

Can the following pattern be achieved with elapsed time queries?

startQueryA
    startQueryB
        startQueryC
        endQUeryC
    endQueryB
endQueryA

Yes, but you'll need to maintain a stack of objects yourself that simulate nested queries on top of multiple individual elapsed time queries. For example, to measure the time under query B above:

virtualizedQueryB = realQuery(startQueryB -> startQueryC) + virtualizedQueryC + realQuery(endQueryC -> endQueryB)
virtualizedQueryC = realQuery(startQueryC -> endQueryC)

query A would be similar, summing in the time for virtualizedQueryB.

If you could write this in a separable helper library that would be awesome. It would surely be useful for a lot of developers.

-Ken

Alecazam

unread,
Jun 3, 2016, 1:38:35 AM6/3/16
to WebGL Dev List
There are easy mechanisms to test for the support of either TIMESTAMP or TIMESTAMP_ELAPSED, so couldn't both be exposed? I was impressed that WebGL got TIMESTAMP queries working on the Mac in first place, since I thought Apple removed support around 10.9 (that's when my calls broke).   The requirement to resolve every timestamp is the main reason for TIME_ELAPSED_EXT being rather pointless.  Often times you're recording a series of timings, and only need to request the outer timings first to determine if the inner timings are even worth requesting.  Timers rollover at 2s on some architectures, but you often don't care, since most timings are sub 1s when you are really looking at frame rate slowdowns.  Even DX doesn't have elapsed GPU timings.  Mobile has the issue of tiling throwing off timings anyways, so I hope this isn't in response to limitations there.

Kirill Dmitrenko

unread,
Jun 7, 2016, 6:45:20 AM6/7/16
to WebGL Dev List
I think we need to update the extension spec then by, for example, removing TIMESTAMP_EXT option entirely. If Chromium or ANGLE team has no intention to support it that'll make timestamps useless.

четверг, 2 июня 2016 г., 4:22:22 UTC+3 пользователь Kenneth Russell написал:

Kenneth Russell

unread,
Jun 7, 2016, 9:14:18 PM6/7/16
to WebGL Dev List
Started a thread on public_webgl at khronos.org about that.

Alecazam

unread,
Jun 8, 2016, 1:14:55 AM6/8/16
to WebGL Dev List
Why are they not implementable on Windows?  I've built whole GPU timing systems on them in the past, and with Nvidia parts on the Mac/PS3/PC.  DX only returns raw timestamps, so how can ANGLE not supply them there?  As stated before, elapsed time has the big limitation that you cannot nest the queries, so you're stuck requesting every time submitted, and then assembling the absolute times from deltas.  Even cpu timers don't work this way, you just take a cpu timing, and can compute deltas from any two timestamps.   All the disjoint timer does is say whether you had wraparound on GL and DX.  I have no idea why Apple thought it was a good idea to remove these, other than because of iOS tiling.  I asked Apple on the OpenGL forums why they removed this, but there was no answer there.   I've built the code below on TIMESTAMP_ELAPSED, but it's really not great flexible, and the assembling timestamps from adding up tiny deltas seems fraught with imprecision.

t0start = -query0
t1start = -query1  <- can nest, or dump timings at any point in the recording

<- if you want timing here, you insert a timestamp query, and add that to close off the open (negative timestamps), reopen (set existing negative timers to the negative of the timestamp here, and can compute the next half of the query

t1end   = +query2
t0end  = +query3

<- compute totalFrame= t0end - t0start.   Only request the sub-timings for t1Start/t1End if above a threshold.  You can also go as deep into the nesting as you want (or request all of them for absolute gpu timings).   Can you elaborate more on why TIMESTAMP_EXT isn't implementable?  
 
 

Alecazam

unread,
Jun 8, 2016, 1:16:25 AM6/8/16
to WebGL Dev List
Oops, I meant totalFrame = t0start + t0end.  That why all open timestamps are negative.

Alecazam

unread,
Jun 8, 2016, 1:28:43 AM6/8/16
to WebGL Dev List
Here are the relavent calls to DX11, but DX9 works the same.  Begin is disabled, since there's not begin/end.  The QUERY_TIMESTAMP is TIMESTAMP_EXT.   There is no TIMESTAMP_ELAPSED implemented, and nesting is fine.  The DISJOINT_TIMER is done once, and indicates whether the timings rolled over, but you can also do that manually with more timings submitted in a frame.  Most timers are 64-bit (many centuries), but some like the OSX still report a 32-bit timer (even for TIMESTAMP_ELAPSED which is about 2s) even though the hardware should have a 64-bit counter by now.

D3D11_QUERY_TIMESTAMP

Get a timestamp value where ID3D11DeviceContext::GetData returns a UINT64. This kind of query is only useful if two timestamp queries are done in the middle of a D3D11_QUERY_TIMESTAMP_DISJOINT query. The difference of two timestamps can be used to determine how many ticks have elapsed, and the D3D11_QUERY_TIMESTAMP_DISJOINT query will determine if that difference is a reliable value and also has a value that shows how to convert the number of ticks into seconds. See D3D11_QUERY_DATA_TIMESTAMP_DISJOINT. When using this type of query, ID3D11DeviceContext::Beginis disabled.

D3D11_QUERY_TIMESTAMP_DISJOINT

Determines whether or not a D3D11_QUERY_TIMESTAMP is returning reliable values, and also gives the frequency of the processor enabling you to convert the number of elapsed ticks into seconds. ID3D11DeviceContext::GetData will return aD3D11_QUERY_DATA_TIMESTAMP_DISJOINT. This type of query should only be invoked once per frame or less.

Kenneth Russell

unread,
Jun 8, 2016, 5:44:10 PM6/8/16
to WebGL Dev List
Thanks for pointing this out Alec. Given this fact I'm not sure why ANGLE didn't expose timestamp queries in its implementation of EXT_disjoint_timer_query. I vaguely recall that bugs were found on various GPUs that rendered timestamp queries useless.

-Ken


--

Alecazam

unread,
Jun 8, 2016, 6:00:45 PM6/8/16
to WebGL Dev List
There's just too many leftovers in GL - there are polled, queried and elapsed timestamps.  The precision should indicate whether there is support or not, so that's why I'm suggesting leaving in both elapsed and queried timestamp support.  Edge, for example, could just feedback the DX timestamps in their implementation, and I'd recommend Angle do the same.  

It's definitely the wrong direction to head towards elapsed timestamps.  They're pointless IMHO, and require extraordinary numbers of request calls to accumulate time for detailed timing.  I had to modify my GPU timing system when Apple pulled GL_TIMESTAMP from OSX.   ES really went the wrong direction with elapsed time, but I can only guess it was because of tiling in the PowerVR and Mali architectures.   Nvidia Tegra, for example, supports full timestamps by extension in ES2 since it's not tiled.   I'm not aware of timestamp bugs in DX9/11 or GL that would prevent their use.  

One issue is timestamp rollover and 32-bit timers, but as long as you have a 64-bit timestamp or intersperse timestamps every 2s on 31/32-bit timestamps then you can detect that by negative deltas and correct them.  Another issue is GPU clock throttling, but you have that with CPUs as well.  The best you can do is plugin the testing device and hope that it doesn't occur.   rtdsc is still faster than QueryPerformanceCounter() for lots of timings, but you also have per-core drift now too.

Kenneth Russell

unread,
Jun 8, 2016, 6:04:52 PM6/8/16
to WebGL Dev List
Per comment on public_webgl, I hadn't realized that for example D3D12 only exposes timestamp, and not elapsed time, queries. It's unfortunate that Mac OS doesn't expose timestamp queries, making them non-portable on a major platform for WebGL 1.0, but I've dropped my request to remove the timestamp queries from WebGL's exposure of the EXT_disjoint_timer_query extension.

-Ken

Alecazam

unread,
Jun 10, 2016, 4:36:47 PM6/10/16
to WebGL Dev List
I can only estimate that Apple dropped them in anticipation of a tiled architecture driving OSX.   That would point to ARM chips driving OSX, but that's been the speculation for a while.  I don't know why they don't offer both on desktop, given the precision query.   The problem with tiling architectures is that your GPU timing numbers have to be accumulated on each pass into elapsed time deltas, but the timings can be dwarfed by the time to sort/bin/tile anyways.  Macro tiling makes sense for lighting and high-complexity blending, but micro-tiling seems less useful below that more and more.
Reply all
Reply to author
Forward
0 new messages