Stamp
Intro
The basic stamp stroke rendering is pretty intuitive. We are given a texture called stamp texture or footprint. While a user paints on a canvas, we render the texture onto the canvas equidistantly along the drawing trace. When the textures are close enough, they seem continuous and form a stroke.

Artists love to create stamp brushes since their expressiveness and intuition. More than 90% of brushes in popular paint software are stamp brushes. Researchers and developers have developed dozens of extra parameters that can apply various aspects of stylization on a stroke. How to replicate these parameters with GPU acceleration is under-researched. Therefore, we will focus on the most critical technique, how to place the footprints in a shader program.
A naive solution is to place a footprint at each vertex.
But it's not good enough for the most usages. The rendering result of strokes depends on polylines' vertex density. After subdivision, simplification, or deformation of the polylines, the strokes get denser or sparser appearance, which ruins the rendering result. We must develop methods that rendering is independent of vertex density, just like rendering 3D meshes. Therefore, I will introduce how to place footprints equidistantly along a polyline.
Locate stamps
When rendering with CPU, calculating where to place footprint (stamp positions) on a polyline is pretty straightforward. Start from the very first vertex of the polyline, place the footprint on the canvas, move along the polyline with the stamp interval to the next stamp position, loop until reach the end of polyline. If we use an image processing library and therefore don't worry about details in placing the footprint, the whole process can programmed within 10 lines of code.

GPU implementation is more challenging, but still relatively straightforward. We use the same approach as rendering a vanilla stroke: Placing the four new vertices for each edge in the vertex shader (or the geometry shader). The difference only comes to the fragment shader.
We will calculate the stamp positions in the fragment shader. At each polyline vertex, we compute its distance to the first vertex along the polyline. The distances represent the cumulative length of the edges, and we calculated them with [Prefix Sum]wiki algorithm.

Parallel prefix sum
There are parallel prefix sum algorithms can be implemented with compute shaders, wiki. By using one of them, the whole rendering process is GPU-accelerated.
The best tutorial about parallel prefix sum I've ever found is this free course High Performance Computing by Prof. Rich Vuduc. The course introduces prefix sum in Lesson 6.
Since we place stamps equidistantly, we can calculate these positions in all pixels involved in each edge. Then a pixel can loop through the positions, sample the stamp textures and determine its color. We compute the texture coordinate with the pixel's distance to the stamp positions and radii.
Loop and sample stamps
A pixel can loop through all stamps on the edge invokes it. But the edge can be very long and has many unnecessary stamps for a pixel to loop through. We want to constrain the loop within only a segment of the edge, within which stamps can cover the current pixel. Given the pixel , we can get this segment by solving the geometry shown in the figure below.

I label the segment can cover the pixel with the thicker black line. The two dashed circles intersect at . Their centers are labeled with vertical line ticks, which are the start and end points of the segment. The centers are the farthest points where a stamp placed can cover the pixel . Any stamps outside the segment have no chance to affect the pixel's color.
In order to get start and end points' positions, we have a geometry puzzle to solve:

As the figure shows, we set up the same local coordinate as vanilla stroke in the shader program. as the origin and X and Y axes align to the tangent and normal direction, as the pixel's local coordinate. is the furthest point's x value. By calculating it, we know the position of farthest point. The distance from the pixel and the furthest point is the radius of the furthest point, whose value is determined by x. To solve the unknown , we can set an equation from the dashed right triangle.
It's not hard to derive from the figure below.
is the length of the current edge.
By replacing , we get a quadratic equation :