Hi there,
Implementing zfreeze has been an Odyssey over the past few years during which multiple developers tried approaching the same issue with a multitude of solutions. To this day, none of them were successful. There is an implementation in the software renderer which was believed to be correct for a while, but it's not, which tells you how little we actually understand about it. This post, while still heavily WIP, seeks to provide an overview of the challenges involved with implementing zfreeze as well as propose a structured "roadmap" of things to be done to get a successful implementation. Additionally, this thread provides a discussion platform on how to proceed with zfreeze related development.
In my opinion, three stages stages need to be considered: Documentation, conception, and implementation. This might sound like it was taken from some standard university lecture, but it seems like a lot of users don't see that indeed there are multiple steps to make and even some of the people who worked on zfreeze seem to try to do all of these steps at once.
Documentation
We have a rough idea of what zfreeze is and how it works. It's similar in concept to an old OpenGL extension (which never was supported widely). Some open questions on the particular implementation remain. The documentation stage seeks to test hardware behavior and summarize it on some public place. Some of the questions seem more obvious than others, and making bad conclusions about "obvious answers" might end in critical design bugs in a later stage.
A lot of these questions will not easily find a definite answer because not all hardware details are accessible via testing. That's the intended point though: Writing tests is easy, coming up with them is the hard part.
What constitutes a reference plane?
Triangles, Quads, Points, Lines? Can all of these be used to set a reference plane?
How does the depth slope of the reference plane get calculated?
Which coordinate system is used (clipspace? screen space? rasterizer space?) ? Is the calculation based on triangle vertices or on 2x2 pixel blocks?
Where does the depth slope of the reference plane get calculated?
With respect to guardband clipping, true clipping, perspective divide, culling, ... It might be calculated before/after/during any of these.
Which steps of the pipeline can prevent a primitive from overriding the reference plane?
An alternative formulation of this question might be "At which point is the depth slope of the reference plane being saved?". This could be immediately after its calculation or later on. This is critical because we might have to calculate the depth slope in an "early" coordinate system, yet might throw it away if the primitive doesn't pass some test.
Conception
Ponder about different ways on how to implement zfreeze in a way that it replicates hardware behavior as accurately as possible. This step is mostly about the hardware renderer implementation, because the conception step is almost trivial for the software renderer implementation.
Scope of the work
Hard to emulate properties of the hardware's zfreeze implementation should be identified and possible solutions be proposed. Can't really get into much more detail until things are documented. The net result of this step is a list of "hard to emulate properties" along with a list to possible solutions for each item.
Proposing a full solution
The proposed solutions for each of the zfreeze properties need to be checked for compatibility against each other ("If I do X, can I still use Y?"). Hopefully some configurations remain, which then are plausible candidates for implementation.
Implementation
Software renderer
It's easiest to implement things in the software renderer, mostly because you don't need to worry about a lot less issues, and also because you can do things easily which would be hard in a hardware renderer. A software renderer implementation should come first in order to verify that our understanding of zfreeze is complete and that all known games behave well with the implementation.
Hardware renderers
Basically the holy grail. Ideally this would happen once we have documented the zfreeze feature well enough, considered different implementation concepts and chose the "best" one, and have a working software implementation.
How to improve this post
Ask questions! I intend to provide a full overview of the issues here. To get things started at all, I only wrote some brief explanations for things, most of which surely lack a lot of details. If you give me some clues, I will elaborate the important aspects.
Implementing zfreeze has been an Odyssey over the past few years during which multiple developers tried approaching the same issue with a multitude of solutions. To this day, none of them were successful. There is an implementation in the software renderer which was believed to be correct for a while, but it's not, which tells you how little we actually understand about it. This post, while still heavily WIP, seeks to provide an overview of the challenges involved with implementing zfreeze as well as propose a structured "roadmap" of things to be done to get a successful implementation. Additionally, this thread provides a discussion platform on how to proceed with zfreeze related development.
In my opinion, three stages stages need to be considered: Documentation, conception, and implementation. This might sound like it was taken from some standard university lecture, but it seems like a lot of users don't see that indeed there are multiple steps to make and even some of the people who worked on zfreeze seem to try to do all of these steps at once.
Documentation
We have a rough idea of what zfreeze is and how it works. It's similar in concept to an old OpenGL extension (which never was supported widely). Some open questions on the particular implementation remain. The documentation stage seeks to test hardware behavior and summarize it on some public place. Some of the questions seem more obvious than others, and making bad conclusions about "obvious answers" might end in critical design bugs in a later stage.
A lot of these questions will not easily find a definite answer because not all hardware details are accessible via testing. That's the intended point though: Writing tests is easy, coming up with them is the hard part.
What constitutes a reference plane?
Triangles, Quads, Points, Lines? Can all of these be used to set a reference plane?
How does the depth slope of the reference plane get calculated?
Which coordinate system is used (clipspace? screen space? rasterizer space?) ? Is the calculation based on triangle vertices or on 2x2 pixel blocks?
Where does the depth slope of the reference plane get calculated?
With respect to guardband clipping, true clipping, perspective divide, culling, ... It might be calculated before/after/during any of these.
Which steps of the pipeline can prevent a primitive from overriding the reference plane?
An alternative formulation of this question might be "At which point is the depth slope of the reference plane being saved?". This could be immediately after its calculation or later on. This is critical because we might have to calculate the depth slope in an "early" coordinate system, yet might throw it away if the primitive doesn't pass some test.
Conception
Ponder about different ways on how to implement zfreeze in a way that it replicates hardware behavior as accurately as possible. This step is mostly about the hardware renderer implementation, because the conception step is almost trivial for the software renderer implementation.
Scope of the work
Hard to emulate properties of the hardware's zfreeze implementation should be identified and possible solutions be proposed. Can't really get into much more detail until things are documented. The net result of this step is a list of "hard to emulate properties" along with a list to possible solutions for each item.
Proposing a full solution
The proposed solutions for each of the zfreeze properties need to be checked for compatibility against each other ("If I do X, can I still use Y?"). Hopefully some configurations remain, which then are plausible candidates for implementation.
Implementation
Software renderer
It's easiest to implement things in the software renderer, mostly because you don't need to worry about a lot less issues, and also because you can do things easily which would be hard in a hardware renderer. A software renderer implementation should come first in order to verify that our understanding of zfreeze is complete and that all known games behave well with the implementation.
Hardware renderers
Basically the holy grail. Ideally this would happen once we have documented the zfreeze feature well enough, considered different implementation concepts and chose the "best" one, and have a working software implementation.
How to improve this post
Ask questions! I intend to provide a full overview of the issues here. To get things started at all, I only wrote some brief explanations for things, most of which surely lack a lot of details. If you give me some clues, I will elaborate the important aspects.