I have dynamic buffers with VAR, but during the runtime of the application, the buffers may be updated :
Never
Somethimes
Almost every frame
And I cannot predict the usage.
3 and 2 does not seem to pose a problem, but the never does, because the application might actually runs for weeks without being stopped.
So the solution I though of is set a fence after each use of the buffer.
After reading the NVFence spec they say that a fence should be left untested or unfinished for a long period time.(they say 2 billion) Obviously if the buffer never gets changed for weeks, then the fence will never be checked or finished.
Does anybody have a solution? Does the warning still applies with the Geforce3?
Fences are fence objects. If you reuse a fence object, then you can no longer query whether the old fence is completed.
I don’t think anyone will allocate 2 billion fence objects (if they do, it will certainly fail before then). So the only way for this to happen is to keep reusing some fence objects, but leave others outstanding.
I don’t see this as proving to be a realistic problem, although it certainly can happen in bizarre circumstances. You should write your app in order to ensure that this problem can’t get hit.
Don’t overuse fences. Too many fences in the command stream will hurt your performance.
Results of TestFence are unreliable when there have been 2 billion intervening SetFence calls since the original SetFence that you are testing. FinishFence may hang your app if there have been 2 billion intervening SetFences.
Or, if a fence has been outstanding for a long time, you could just know that it’s done rather than testing it – something you should probably do anyhow. (For one, fences complete in order, and you should take advantage of this because it can save you tests/finishes.)
Fences are not anything like mutexes.
If your app uses 20 fences per frame (which would be a fairly high number to use), and you run at 60 fps, your app would run for 19 days before using 2 billion fences.
No, it’s 2 billion SetFence calls across all fence objects.
It sounds like your approach will use too many fences, for one thing. Reuse a small number of fence objects and don’t use many SetFence calls per frame. Take advantage of the fact that you do know how your app will behave. For example, for static geometry, never use a fence.
You will need to design an approach that doesn’t encounter this problem.
If I understand fences correctly, any time you call glFlush, all of the currently set fences will be finished, since that is part of the rendering pipeline.
I was unaware that if you just reused the same fence with glSetFence that you would evern encounter a problem. Although 2 billion is quite a bit, one may want to have several hundred fences set per frame in order to provide good asynchronous rendering.
No, if you call glFinish, all previous fences can be known to have completed. glFlush does not guarantee that anything has completed.
If you reuse just one fence object, the problem can never happen, because only one fence can be outstanding at any given time. It can happen with two or more.
Also note the comment in the extension that you may get fewer than 2 billion because of our internal use of fences.
Yes, it is OK to go ahead and re-use a fence that’s set sometime previously. You could actually just use some small number of fences, and loop through them if you wish.
Something like the below might work (modulo arguments missing :-). Note that this is not ideal, because you’re setting a large number of fences.
So what will happen if the fence assigned to some buffer gets re-set by some other buffer? Well, you’ll wait until that buffer is finished, too, which is OK because that buffer is guaranteed to be finished after the buffer you’re waiting on. You may stall the pipeline if you happen to start waiting on a very recently set fence.
There are a gazillion different ways you can structure this, but which one is the best is very dependent on how you use the buffers, and whether you know beforehand whether this buffer is likely to get re-used or not.
Is is ok to set a fence only once per frame and not call glFinishFenceNV between the frames?
Yes. This is equivalent to re-setting a fence which has been set before. There’s nothing special or magical about SwapBuffers (well, at least not in the spec
As setting lots of fences will slow you down, you might want to set a fence for every 10 buffers you draw, and just put a counter in each buffer which frame number and which buffer number you last drew it. Then when time comes to update the buffer, wait on the fence you set at or after that counter value.
Gorg,
I’m not sure this is a real problem in practice, but…
I wouldn’t set the fence every frame if you don’t intend to call glFinishFenceNV on it. If you’re worried about waiting too long, why not set the fence every time
a) the object is updated
or
b) every hour since last updated (even if you’re not drawing the corresponding geometry)
Of course you need to finish the fence if you need to reclaim the memory that it consumes.
OK.From everybodys comments I think I finally understand now what the spec means.
Somebody confirm.
If I set a fence(let’s called f1), then set 2 billions other fences, then If I check f1 I will get the issues that Matt said described in an earlier post.
It that is true then I had no problem aside from using too many fences.
This might not be exactly relevant to this topic, but I need to ask somewhere, and don’t fancy the idea of starting a new topic only to be shouted down for some reason.
First question:-
SwapBuffers must complete all drawing operations before spewing the final image to the monitor - correct? So why use fences, unless you’re modifying the same data multiple times within a single frame?
Anyway, I want to describe my water rendering process, so as to gleen some knowledge from you kind people:-
Initialisation Stage: grab some of the AGP memory I allocated at app initialisation time.
Loop:-
…FinishAllFences
…Update y value of all vertices in my AGP array with a new height value
…Render tiles, using the single AGP vertex array, here is the code:-
Now, my question(s) is this:-
I seem to have to set a fence for every tile (I’m using the same vertices & indices for every tile).
If I don’t, I get splits appearing between the tiles every-so-often.
I think I know why, but it would be nice to have it confirmed.
Another question about general efficiency.
I update the vertices every frame, before rendering. I am targetting this project at a dual P4 1.8ghz, but for some reason, doing a few simple multiplications on every vertex in a 64x64 grid of floats impacts performance severely - why? How can I make full use of these powerful processors?
I don’t understand how your suggestion would work. If I only set a fence when I’m updating the buffer, how would that protect me from messing with vertex data while it’s being used. Consider:
Update Buffer
Time Passes
Render Buffer
Update Buffer
I will have to set a fence AFTER any operation that USES the buffer to be sure that I can safely update the buffer. Thus, it doesn’t seem to me that setting a fence after updating it will give me anything. I might as well finish the entire vertex array range before each buffer update in that case.