Question about zbuffer
losanc opened this issue · 2 comments
losanc commented
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.
losanc commented
I see, thanks