Performance and hardware

The application uses your graphics card. The batch tool does not. That sounds like a gap and mostly is not one, and this page explains both halves so you can tell whether something is slow for a reason.

The GPU, in the editor and in the batch tool

In the editor, the work is done on your graphics card when one is available. The status bar says GPU or CPU for every solve, so you never have to guess which you got.

With a tile grid on it says Tiles instead. That is the CPU by choice, not a fallback: each tile is small, only the tiles you changed are solved again, and a stroke on a tile sheet comes back in milliseconds.

On Linux, the editor draws its window with WebKitGTK, which cannot reach the graphics card. So it starts the batch tool beside itself and hands it the solves, and the batch tool reaches the card through Vulkan. The status bar says GPU when that works, as on Windows. It needs a Vulkan driver, which Mesa and NVIDIA's own driver both provide; a software-only one is not used, because it would be slower than the CPU path. The first sprite of a session can solve on the CPU while the batch tool starts.

In tnmap, the batch tool, solves run on the graphics card too. New in 1.6.1. Before the first sprite, a run says which it got: GPU: and the card, or CPU: and the reason it could not use one. The solve itself is the same solver the editor runs, and on a large sprite it is several times faster — a 1542×1095 sheet went from 17 seconds to under 2 on the machine it was measured on. Height and ambient occlusion are worked out on the card as well. A tile grid is solved tile by tile on the CPU, as it is in the editor.

How much faster a whole run gets depends on what else the settings ask for. Reading drawn strokes, detail methods such as bevel, and writing the files stay on the CPU, so on a sprite that leans on those the run gains less than the solve does.

--cpu keeps a run on the CPU. The two agree the way the editor's GPU and CPU do, to a fraction of a degree, except that a pixel sitting exactly on the line between ink and not-ink can land on either side. Use --cpu when a run has to match an earlier CPU run byte for byte.

When the editor falls back to the CPU

Capability is detected rather than assumed. If your graphics card cannot be used, the editor uses the CPU and says so in two places: CPU in the status bar, and a line in the inspector's Solve detail section explaining why.

That second part is the one that matters, because "why" is usually actionable. Common causes are a browser or webview without a working graphics backend, a driver that declines the request, or a machine with no discrete graphics at all.

A graphics card that was working can also drop out in the middle of a solve: the driver resets, or the browser loses the device. That solve finishes on the CPU instead of stopping with an error. The status bar says CPU, and Solve detail says the device was lost. The next solve tries the graphics card again. If that one dies too, the rest of the session stays on the CPU. Reload the editor to give the card another chance.

The result is identical either way. The CPU path and the GPU path produce the same normal map — they are held to that deliberately, because two plausible normal maps that disagree is a far worse failure than a slow one. Both methods run on the GPU when one is available, including luminance: that path used to skip it, and a large sprite then froze the editor.

Height and ambient occlusion are a second job after the solve, and they used to run on the UI thread — which is why switching to the Height view on a large sprite locked the window. They now use the same graphics worker. Specular does not: it is a brightness reading of the artwork, cheap enough to stay on the CPU.

Apply extra maps in Lit used to drop the preview off the GPU and shade every pixel of the sprite on the CPU, and each remap cloned the sprite back to the worker. Both of those locked a 2048-square image while you worked. Lit with extras now stays on the GPU (Lambert until the maps arrive, then AO and spec in the same pass), and the worker reuses the grids it already holds.

Live updates on a slow sprite

By default the result updates as you work: as you drag a slider, as you paint a stroke. It stays that way however slow a sprite is to solve, unless you turn it off. New in 1.7.0; until then a slow solve switched live updating off by itself.

  • While a solve is taking a while, the picture fades a little and a spinner sits over it. You can keep working: painting and dragging carry on underneath.
  • If you change something while a solve is running, that solve is abandoned at its next step and your newest change is solved instead, so you wait for the picture you asked for last rather than every one in between. The spinner stays up until it arrives.
  • When a full solve takes longer than about half a second, a banner says how long, with a Turn off live updates button. Close the banner to keep working live; it asks again for the next sprite.

With live updates off, changes wait until you press Solve. Switch them back on and off with Update live in the options bar or View ▸ Live updates.

Drafts

While you are dragging something, the editor may show a draft — a lower-quality approximation, computed quickly, replaced by the full result when you stop. The inspector's Solve detail section reports which you are looking at.

Dragging a light shades the visible pane, plus a little extra around the edges, rather than the whole sprite. Zooming in on a large document keeps that drag sharp. Zoomed out, a huge sprite may still draft at a lower resolution so the pointer stays attached to the picture.

Drafts are for keeping the picture attached to your hand. A draft cannot be exported, and the export command is unavailable while one is showing.

What makes a solve expensive

Roughly in order of impact:

  1. Sprite size. Cost scales with the pixel count, so a 1024-square sheet is far more than four times a 512-square one in practice.
  2. Follow overall form. On, the overall shape has to be worked out before the detail is laid over it. Off, that work disappears.
  3. Detail methods. Each one with a weight above zero is extra work. They are cached per sprite, so changing a weight is much cheaper than switching a method on.
  4. Painted hints are cheap. Paint freely.

The first solve of a session

The first solve after opening the application is slower than the ones after it — the graphics pipeline has to be prepared before anything can run on it, and that is a fixed cost paid once. It is deliberately started before you have opened a sprite, so most of it overlaps with the application loading.

You may also see one unusually slow solve after leaving the application idle for a while. That is your graphics card having dropped to a low clock speed while nothing was asking anything of it, and it recovers on its own within a solve or two.

What the packaged application is

The desktop build uses your operating system's own web view rather than bundling a browser: WebView2 on Windows, and WebKitGTK 4.1 on Linux, which your distribution provides. That keeps the download small and means security updates arrive through the operating system rather than waiting for a release here.

It is a desktop application, not a browser tab. There is no address bar, and it does not need a network connection — nothing about your artwork leaves your machine.