ssloy / tinyrenderer

A brief computer graphics / rendering course
https://github.com/ssloy/tinyrenderer/wiki
Other
20.68k stars 1.98k forks source link

Question about zbuffer #129

Closed losanc closed 1 year ago

losanc commented 1 year ago

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 1 year ago

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.

losanc commented 1 year ago

I see, thanks