ssloy/tinyrenderer

Question about zbuffer

losanc opened this issue · 2 comments

here is a snippet of the code about zbuffer. Won't this cause data race?

#pragma omp parallel for
    for (int x=std::max(bboxmin[0], 0); x<=std::min(bboxmax[0], image.width()-1); x++) {
        for (int y=std::max(bboxmin[1], 0); y<=std::min(bboxmax[1], image.height()-1); y++) {
            vec3 bc_screen = barycentric(pts2, {static_cast<double>(x), static_cast<double>(y)});
            vec3 bc_clip   = {bc_screen.x/pts[0][3], bc_screen.y/pts[1][3], bc_screen.z/pts[2][3]};
            bc_clip = bc_clip/(bc_clip.x+bc_clip.y+bc_clip.z); // check https://github.com/ssloy/tinyrenderer/wiki/Technical-difficulties-linear-interpolation-with-perspective-deformations
            double frag_depth = vec3{clip_verts[0][2], clip_verts[1][2], clip_verts[2][2]}*bc_clip;
            if (bc_screen.x<0 || bc_screen.y<0 || bc_screen.z<0 || frag_depth > zbuffer[x+y*image.width()]) continue;
            TGAColor color;
            if (shader.fragment(bc_clip, color)) continue; // fragment shader can discard current fragment
            zbuffer[x+y*image.width()] = frag_depth;
            image.set(x, y, color);
        }
    }

Because everything is parallel. So it's possible that it may compute 2 different fragment point, but which is the same pixel on the screen. And if both of the fragment point has lower depth than current value in the zbuffer. Then the comparison frag_depth > zbuffer[x+y*image.width()] will both return true. Then the writing zbuffer[x+y*image.width()] = frag_depth; may be wrong, because it's unknown which value will be written

ssloy commented

Nope, it is safe. There is no parallel for for triangle assembly, only rasterization is made in parallel, and every pixel of the bounding box is visited exactly once.

I see, thanks