WebGL is it possible to emulate an asynchronous call to gl.finish() - webgl

WebGL is nice and asynchronous in that you can send off a long list of rendering commands without waiting for them to complete. However, if for some reason you do need to wait for the rendering to complete, you have to do it synchronously with gl.finish(). Surely it would be better if gl.finish accepted a callback and returned immediately?
Question: Is there any way to emulate this reliably?
Usage case: I am rendering a large number of vertices to a large off-screen canvas and then using drawImage to copy sections of this large canvas to small canvases on the page. I don't actually use gl.finish() but drawImage() seems to have the same effect. In my application, re-rendering is only triggered when the user performs an action (e.g. clicking a button), and it may take several hundred milliseconds. It would be nice if during rendering the browser was still responsive allowing scrolling etc. I am looking in particular for a Chrome solution, though something that also works in Firefox and Safari would be good.
Possible (bad) answer: You could try and estimate how long rendering is going to take and then set a timeout that begins with the call to gl.finish(). However, reliably doing this estimation for all sizes of vertex buffer and all users is going to be pretty tricky and inaccurate.
Possible (non-)answer: requestAnimationFrame does what I'm looking for...it doesn't though, does it?
Possible answer in 2018: Perhaps the ImageBitmap API solves this problem - see MDN docs.

You've already partially hit on your answer: drawImage() does indeed have finish-like behavior in that it forces all outstanding drawing commands to complete before it reads back the image data. The problem is that even if gl.finish() did what you wanted it to, wait for rendering to complete, you would still have the same behavior using it as you do now. The main thread would be blocked while the rendering finishes, interrupting the user's ability to interact with the page.
Ideally what you would want in this scenario is some sort of callback that indicates when a set of draw commands have been completed without actually blocking to wait for them. Unfortunately no such callback exists (and it would be surprisingly difficult to provide one, given the way the browser's internals work!)
A decent middle-ground in your case may be to do some intelligent estimations of when you feel the image may be ready. For example, once you have dispatched your draw call spin through 3 or 4 requestAnimationFrames before you call drawImage. If you consistently observe it taking longer (10 frames?) then spin for longer. This would allow users to continue interacting with the page normally and either produce no delay when doing the draw image, because the contents have finished rendering, or much less delay because you do the synchronous step mid-way through the render. Depending on the intended usage of your site non-realtime rendering could probably even stand to spin for a full second or so before presenting.
This certainly isn't a perfect solution, and I wish I had a better answer for you. Perhaps WebGL will gain the ability to query this type of status in the future, because it would be valuable in cases like yours, but for now this is likely the best you can do.

Related

performSelectorInBackground called method slowing down main thread - can that be fixed?

The client wrote a REST API for their website before ever starting on an app. it's a nice API, but it was designed to interact with a service that's running on the same network. The client didn't account for the fact that interaction over cellular data would take an exponentially longer amount of time than interaction on the same network, or even the same physical computer. Due to the fact that the client didn't account for this during server design, I am now left with an API that requires I transfer an entire object back and forth every single time the user changes 1 option. At first, it was slowing my main thread down by a ridiculous amount. So, I attempted to fix the problem by putting the API interaction on a background thread with a call to
[self performSelectorInBackground:]
This helped a great deal. However, the graphics are still a little bit choppy. The speed at which the data is transferred and returned isn't overly important, as long as it happens. I was wondering if there's a method of lowering the background thread's priority so that the graphics on the main thread aren't affected at all, or at least, very little. Is that possible?
By default, running a method on the background thread is lowering the priority below the main thread, so it should not be slowing the main (UI) thread. I would guess there is something else going on. I would venture that you are doing something else on the main thread that you are not aware of that is slowing down your "graphics". To check, try stubbing out your server calls, because there is almost no way that a download / parsing of data on the background thread would slow things to the point where the main thread would get hung and cause animations to stutter. The other possibility is that your animations are not done efficiently and are just choppy themselves.
You will need to be more specific with what you mean by the graphics being choppy to get a better answer, though.

How to do UITableView operation queues to download concurrently

I am doing a UITableview to download data
the name webservice is very fast, so I use it to populate the table initially, then I start an operation queue for the image.
Then a seperate queue for the rest of data because it loads very slow but that effects the image load time, How can I do the 2 concurrently.
Can you figure out whats slowing the performance there and help me fix it?
As I assume you know, you can specify how many concurrent requests by setting maxConcurrentOperationCount when you create your queue. Four is a typical value.
self.imageDownloadingQueue.maxConcurrentOperationCount = 4;
The thing is, you can't go much larger than that (due to both iOS restrictions and some server restrictions). Perhaps 5, but no larger than that.
Personally, I wouldn't use up the limited number of max concurrent operations returning the text values. I'd retrieve all of those up front. You do lazy loading of images because they're so large, but text entries are so small that the overhead of doing separate network requests starts to impose its own performance penalties. If you are going to do lazy loading of the descriptions, I'd download them in batches of 50 or 100 or so.
Looking at your source code, at a very minimum, you're making twice as many JSON requests as you should (you're retrieving the same JSON in getAnimalRank and getAnimalType). But you really should just alter that initial JSON request to return everything you need, the name, the rank, the type, the URL (but not the image itself). Then in a single call, you get everything you need (except the images, which we'll retrieve asynchronously, and which your server is delivery plenty fast for the UX). And if you decide to keep the individual requests for the rank/type/url, you need to take a look at your server code, because there's no legitimate reason that shouldn't come back instantaneously, and it's currently really slow. But, as I said, you really should just return all of that in the initial JSON request, and your user interface will be remarkably faster.
One final point: You're using separate queues for details and image downloads. The entire purpose in using NSOperationQueue and setting maxConcurrentOperationCount is that iOS can only execute 5 concurrent requests with a given server. By putting these in two separate queues, you're losing the benefit of maxConcurrentOperationCount. As it turns out it takes a minute for requests to time out, so you're probably not going to experience a problem, but still, it reflects a basic misunderstanding of the purpose of the queues.
Bottom line, you should have only one network queue (because the system limitation is how many network concurrent connections between your device and any given server, not how many image downloads and, separately, how many description downloads).
Have you thought about just doing this asyncronously? I wrote a class to do something very similar to what you describe using blocks. You can do this two ways:
Just load async whenever cellForRowAtIndexPath fires. This works for lots of situations, but can lead to the wrong image showing for a second until the right one is done loading.
Call the process to load the images when the dragging has stopped. This is generally the way I do things so that the correct image always shows where it should. You can use a placeholder image until the image is loaded from the web.
Look at this SO question for details:
Loading an image into UIImage asynchronously

How to get notified when glTexImage2D finished upload?

I want to render after a texture is uploaded to OpenGL, but I cannot get notified about the completition.
I do want to avoid using animation, or any kind of repetitive rendering.
Is glTexImage2D asynchronous at all? As far as I know, almost every OpenGL call is async.
It would be great anyway, if I could be informed about a glDrawArrays completition as well.
The answer is, just continue after the call to glTexImage2D returns. From your point of view it is a synchronous call in the sense that everything is properly set up after it returns. You can make texture uploads asynchronous by using PBOs as intermediate storage, but even then everything is managed by the driver for you and all you need to know is that when glTexImage2D returns you can assume the texture data to be properly uploaded and start rendering. If the texture data is not yet uploaded internally your things won't get rendered anyway and will wait for the texture to be set up.
You are correct that most OpenGL calls can be seen as asynchronous in the sense that they only schedule commands to be sent to the graphics card and the driver decides when to finally send them to the hardware and the hardware is free to decide when to process them, not to speak of the fact that nobody knows when they're actually finished. But you know what, you usually just don't care. If anything needs to block in order to wait for some previous operation to complete (like an asynchronous texture upload), then it will be managed for you automagically and once an OpenGL function returned you can be sure it has done its work from your point of view.
disclaimer: There are indeed situations when you really need to know when an actual operation has finally finished its work on the device. Though your scenario isn't one of those. One of the few situations when you might really want to synchronize operations is, when you are timing something for debugging or profiling reasons. And since OpenGL ES probably lacks ARB_timer_query, issuing a glFinish (like suggested in BlueVoodoo's answer) might be an option in this case.
EDIT: In the same way you don't get notified when your things drawn with glDrawArrays are finally rendered to screen, but you just don't care about it.
I guess you meant it's an asynchronous call? Otherwise, why do you need to get notified? If you need it to be synchronous, have a look at glFinish(). I don't know of any notifications for openGL methods.

Processing uploaded images asynchronously: what to do in the meantime?

I need to accept images uploaded by the users, and do some processing in the background, like generating different size thumbnails, a checksum for the original image, check for duplicates, etc. After that, the user should be able to see his submission.
The problem is that the http response will probably be sent before the processing is finished, so what do I tell to the user?
I can think of 4 options:
Put a dumb placeholder for the thumbnails, with a sign that reads 'processing' or something, plus an explanation somewhere. The user will have to press f5 until he sees the image, unless he already trusts the system and knows it's going to work.
Put a smart placeholder, something like a javascript animation plus recurring ajax calls that will fetch the thumbnails when they are ready. This is great for the user experience, but might generate some overhead in the server.
Do the processing asynchronously to avoid overloading, but block the request until the processing is finished. This one looks like a good choice to deliver the product fast, and iterate later if the server starts getting many upload at the same time.
Web sockets?
Are there other options? Which one looks better to you? Are there any pros/cons I'm not seeing?
I would go with
"Put a smart placeholder, something like a javascript animation plus recurring ajax calls that will fetch the thumbnails when they are ready. This is great for the user experience, but might generate some overhead in the server."
You can then refine this further based on analytics. With time you will know how long each image would takes to transform based on factors like image size, server-load etc. You can incorporate this knowledge to optimize your JS scripts that poll for results.
Don't try to optimize without data points and profiling.

Why not compile shaders on a background thread?

I've been learning OpenGL ES 2.0/GLSL and related iOS quirks by looking at code and developer videos and I've noticed that there's never any mention of asynchronous shader compilation. Aside from instructors, writers, or salesmen (er, engineers) worrying about adding complexity to their examples, is there a reason for that?
For example, most web data retrieval tutorials hammer home the need for doing some sort of gymnastics (pthreads, NSOperation, GCD, baked in asynch instance methods, etc) to keep from blocking the main thread- why would blocking an app launch be considered acceptable?
It can be a little bit tricky to synchronize two EAGLContext's, beside that, there is nothing against loading this kind of stuff in the background (generally, loading every kind of asset, textures, shaders etc).
Probably the real reasons are that most people think of OpenGL (ES) as something monolithic that only works on one single thread or they never had an issue with loading times that made it worth to load stuff in a background thread or they just don't care (for some people its probably everything together).
For your last question: Networking can add a HUGE latence and with "can" I mean "will". Resource loading isn't that problematic, compared to a network access, loading a shader or texture takes way less time and its already known ahead how much time it will take in the normal case. Plus, people are used to loading screens in game while they don't want to see loading screens when they scroll a table view just so that your application can fetch a picture from a server that doesn't respond.

Resources