Archived

This topic is now archived and is closed to further replies.

Occlusion Query

This topic is 5038 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I'm trying to use the new feature in DX9, Occlusion Queries. But I have a problem: IDirect3DQuery::GetData always(!!) returns S_FALSE! I have a Geforce 4 Ti 4200, driver is relatively new. Here's some of my Code (for testing purposes): m_RenderSystem.ClearScreen(true,true); m_VB->Bind(); m_RenderSystem.GetDevice()->SetFVF(sVertex::FVF); m_RenderSystem._SetCullMode(CULL_NONE); cRenderOperation Op; Op.VertexBuffer=m_VB; Op.Operation=cRenderOperation::OP_TRIANGLE_LIST; m_Query->Begin(); m_RenderSystem._Render(Op); m_Query->End(); uint Count; if(m_Query->GetVisiblePixels(Count)) cLog<<"Visible Pixels: "<< Count <<"\n"; [edited by - SlimTimmy on February 22, 2004 3:29:48 PM] [edited by - SlimTimmy on February 25, 2004 11:06:22 AM]

Share this post


Link to post
Share on other sites
How are you using the GetData() call? It should be like this:
 while (d3dQuery->GetData((void *) &occlusionVariable, sizeof(DWORD), D3DGETDATA_FLUSH) == S_FALSE);  

You need the while loop because GetData() is asynchronous, so it normally doesn''t succeed the first time.

Share this post


Link to post
Share on other sites
quote:
Original post by SlimTimmy
Ok, now it works, but is it really necessary to use D3DGETDATA_FLUSH? I thought, that such a call can result in a lost device.

Flushing forces D3D to send the query commands to the driver. Without flushing, you could wait a little longer for d3d to pass the commands to the driver, then for the driver to do the query.

Muhammad Haggag
[edit]Correction[/edit]

[edited by - Coder on February 23, 2004 6:17:41 AM]

Share this post


Link to post
Share on other sites
That would probably depend on you card/driver settings, because every driver should have a different FIFO pipeline.
Generally I would advise you to send all your occlusion queries at once, and then flush the FIFO. This way the Queries will be queued up and you only need to flush once.


Hey, SlimTimmy, I know you from the ZFX forums, don''t I? ^^

cya,
hWnd

Share this post


Link to post
Share on other sites
When wouldn''t you use the D3DGETDATA_FLUSH-parameter?
I did a test and just passed 0 as the last parameter of the GetData-method, the condition in the while-loop (see above) never evaluated to true! Is this a normal behaviour?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:

When wouldn''t you use the D3DGETDATA_FLUSH-parameter?
I did a test and just passed 0 as the last parameter of the GetData-method, the condition in the while-loop (see above) never evaluated to true! Is this a normal behaviour?



That is the behaviour I would expect, because the query is never sent to the video card.

The driver internally has a FIFO queue where all commands that have to be sent to the card are stored. When the queue is full, it will be flushed, i.e. sent to the card. There are some operations that cause the command queue to flush, no matter if it''s full or not. These commands include swapping front and back buffer and render target changes. In GL there is also a convenient way to flush the pipeline manually, using glFlush(). I do not know of a similar way to do this in D3D.

So in your case, the query is added to the queue, but since it is never flushed the query is never issued.

Share this post


Link to post
Share on other sites
quote:
Original post by SlimTimmy
When wouldn''t you use the D3DGETDATA_FLUSH-parameter?
I did a test and just passed 0 as the last parameter of the GetData-method, the condition in the while-loop (see above) never evaluated to true! Is this a normal behaviour?

My understanding is that if you don''t specify the FLUSH flag, don''t loop. When you don''t specify the flag, you''re expected to check after doing some more graphical operations (i.e. the next frame or whatever, obviously that doesn''t work when you need the query results for the next frame, but that''s only one scenario).

Muhammad Haggag

Share this post


Link to post
Share on other sites
quote:
Original post by Coder
(i.e. the next frame or whatever, obviously that doesn''t work when you need the query results for the next frame, but that''s only one scenario).
I was thinking about that, because I assume all of those while loops do take a good bit of processing time. What you may be able to do is:
(1) Query the data
(2) If it isn''t ready, just use the queried data you already have (from past frames)
(3) Next frame around, check again
Yea, you''ll be using past frame''s queries, but how much does the scene really change in the span of 1-3 frames?

Share this post


Link to post
Share on other sites
quote:
Original post by circlesoft
How are you using the GetData() call? It should be like this:
 while (d3dQuery->GetData((void *) &occlusionVariable, sizeof(DWORD), D3DGETDATA_FLUSH) == S_FALSE);   

You need the while loop because GetData() is asynchronous, so it normally doesn''t succeed the first time.


This defeats the Asynchronous aspect. Drivers typically have 2-3 frames queued up. The whole point of Asynchronous queries is so that you don''t have to stall the whole pipeline. The correct thing to do is come a few frames later and see if its ready.

You can''t use the asynchronous event to do any kind of optimization since it is a few frames late. The best use for it is for lens flares and corona''s, where you don''t care if its a a few frames behind.

Share this post


Link to post
Share on other sites
quote:
Original post by EvilDecl81
This defeats the Asynchronous aspect. Drivers typically have 2-3 frames queued up. The whole point of Asynchronous queries is so that you don''t have to stall the whole pipeline. The correct thing to do is come a few frames later and see if its ready.
That''s how ATI does it.

quote:
Original post by EvilDecl81
You can''t use the asynchronous event to do any kind of optimization since it is a few frames late. The best use for it is for lens flares and corona''s, where you don''t care if its a a few frames behind.

What if you are using the query for occlusion culling? You do need that data within a frame or two, but the viewing frustum is not going to move so drastically in the span of 1-2 frames that the entire viewport is offset. Especially since you are running on new graphics cards (this means higher framerates, less camera movement).

Share this post


Link to post
Share on other sites
quote:
What if you are using the query for occlusion culling? You do need that data within a frame or two, but the viewing frustum is not going to move so drastically in the span of 1-2 frames that the entire viewport is offset. Especially since you are running on new graphics cards (this means higher framerates, less camera movement).

There''s a GL demo at Delphi3D.net that uses occlusion queries for the real-time display of a 13 Million triangle factory model. With only 1000 lines of code.


Muhammad Haggag

Share this post


Link to post
Share on other sites
quote:
Original post by EvilDecl81
This defeats the Asynchronous aspect. Drivers typically have 2-3 frames queued up. The whole point of Asynchronous queries is so that you don''t have to stall the whole pipeline. The correct thing to do is come a few frames later and see if its ready.

You can''t use the asynchronous event to do any kind of optimization since it is a few frames late. The best use for it is for lens flares and corona''s, where you don''t care if its a a few frames behind.

- Some people already force the driver to synchronize with the renderer, by using queries or locking 1x1 textures that are used to render dummy objects or locking the back-buffer (UT2K3).

- I believe GetData() isn''t intended for asynchronous use only, it can be used syncrhonously when the query results are needed *now*.

Muhammad Haggag

Share this post


Link to post
Share on other sites
I don't need the results of the query immediately! (I want to use it for lens flare effects) But do I have to create a new query every frame and check it later?
If I use just one query-object then the GetData-methode (always!!) returns S_FALSE. What should I do?

[edited by - SlimTimmy on February 25, 2004 8:43:54 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by Coder
There''s a GL demo at Delphi3D.net that uses occlusion queries for the real-time display of a 13 Million triangle factory model. With only 1000 lines of code.
Thanks, man, that''s sweet. I''ll definetly look into that

quote:
the GetData-methode (always!!) returns S_FALSE

Timmy, does it return false even a frame or two later? You could check to see if the data is available. If it returns S_FALSE, do not reset the query (query->Begin()) for that frame. If it gives you your data, then reset the query and start again.

Share this post


Link to post
Share on other sites
Yes, that was my problem. I reset the Query by issuing an new one.
Which way should I go for a lens flare effect:
(1) Issue just one query at a time, I would get new information only every 2-3 frames
(2) Issue every frame a new query

I think the first method would be ok.

Share this post


Link to post
Share on other sites
I did a test and it works fine:

static bool DoQuery=true;


if(DoQuery)
m_Query->Begin();

m_RenderSystem._Render(Op);

if(DoQuery)
m_Query->End();

uint Count;
if(m_Query->GetVisiblePixels(Count))
{
DoQuery=true;
cLog< }
else
{
DoQuery=false;
cLog<<"no data available\n";
}

And the output in the log file:

no data available
no data available
210
no data available
no data available
no data available
210
no data available
no data available
210
no data available
no data available
no data available
210

Looks fine. Thank you!

[edited by - SlimTimmy on February 25, 2004 11:04:21 AM]

Share this post


Link to post
Share on other sites