VK_EXT_depth_bias_control
This document details API design ideas for the VK_EXT_depth_bias_control
extension,
which provides functionality for finer control over the behavior and representation
of depth bias when rendering.
1. Problem Statement
Some applications and API layering efforts, e.g., D3D9, need a way for depth bias to be represented in exact
terms as if it were depth = depth + depth_bias
in the shader, rather than being format-dependent.
In some older APIs, applications can specify extreme depth bias values, such as
0.5f
, as a direct offset to be applied. Translation layers can attempt to
simulate this behavior by multiplying the application-provided direct bias by
1/r
and passing the result as depthBiasConstantFactor
. However, the current
specification does not set a fixed value for r
in fixed-point attachments, and
its value can also vary per-primitive when using floating-point attachments.
This leads to incorrect depth bias values being applied, and the error is larger
the larger the fixed depth bias is.
API layering efforts regularly need to emulate certain depth formats such as VK_FORMAT_D24_UNORM_S8_UINT
using higher-precision formats
such as VK_FORMAT_D32_SFLOAT_S8_UINT
. This creates an additional problem as the minimum resolvable difference for SFLOAT
formats is defined differently compared to UNORM
formats.
This means we need a way to prevent implementations from applying a 2x scaling
factor to the value of r
when using fixed-point attachments, and a way of
treating the depth bias' minimum resolvable difference in linear terms (like
UNORM
formats) for SFLOAT
formats.
2. Solution Space
-
Solve from the application side by hardcoding
r * n
values for each driver-
This is problematic because it means an application must be aware of and hardcode implementation-specific to work around the problem.
-
-
Solve from the application side with
r * n
resolution-
The application could attempt to resolve the scaled
r * n
values by drawing a quad with a known depth bias value and reading back the depth. This is problematic because it does not solve the issue regarding the minimum resolvable difference being scaled differently forSFLOAT
formats.
-
-
Solve from the application side with shader-side biasing using
gl_FragDepth
-
Another option from the application side is to use a push constant and perform depth-bias manually in the shader. This is problematic as it can lead to reduced performance as this avoids early-z optimizations.
-
-
Add a method of specifying the depth bias representation
-
A Vulkan extension could be made to provide functionality to specify the representation and scaling of depth bias that is wanted.
-
3. Proposal
Add a new function, vkCmdSetDepthBias2EXT
that uses an extendable VkDepthBiasInfoEXT
.
Add a new structure, VkDepthBiasRepresentationInfoEXT
, that can be added to the pNext
chain of a pipeline’s VkPipelineRasterizationStateCreateInfo
state or VkDepthBiasInfoEXT
in a vkCmdSetDepthBias2EXT
call that allows setting the scaling and representation of depth bias for a pipeline.
It will support specifying if the representation should be format-dependent, the behavior of UNORM
formats, and whether or not the depth bias should be scaled to ensure a minimum resolvable difference.
struct VkDepthBiasInfoEXT {
VkStructureType sType; // VK_STRUCTURE_TYPE_DEPTH_BIAS_INFO_EXT
const void* pNext;
// Same as the params to vkCmdSetDepthBias.
float depthBiasConstantFactor;
float depthBiasClamp;
float depthBiasSlopeFactor;
};
void vkCmdSetDepthBias2EXT(
VkCommandBuffer commandBuffer,
const VkDepthBiasInfoEXT* pInfo);
enum VkDepthBiasRepresentationEXT {
// The default behavior of Vulkan.
// Depth bias as a factor of `r`, format-dependent.
VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT = 0,
// Depth bias as a factor of constant `r` UNORM behavior.
VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT = 1,
// Depth bias as a raw floating-point value, same effect as doing `gl_FragDepth = gl_FragCoord.z + d`.
VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT = 2,
};
// Part of the pNext chain of a VkPipelineRasterizationStateCreateInfo.
struct VkDepthBiasRepresentationInfoEXT {
VkStructureType sType; // VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT
const void* pNext;
VkDepthBiasRepresentationEXT depthBiasRepresentation; // The depth bias representation for the pipeline
VkBool32 depthBiasExact; // Whether or not the depth bias should be scaled to ensure a minimum resolvable difference
};