bkaradzic/bgfx

Sampler border color inconsistencies across platforms (some code included)

EvilTrev opened this issue · 0 comments

Describe the bug
When using sampler border color, there are inconsistencies across platforms that I believe can be improved with a few changes.

First up Vulkan defaults to:

sci.borderColor      = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;

Whereas DX when not provided a color uses:

_rgba = s_zero.m_zerof;

On Vulkan, opaque black contains 1.0 in the alpha, whereas on DX s_zero contains 0.0 in the alpha. I believe Vulkan should probably read as follows to be consistent:

sci.borderColor      = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;

Next up there's metal, which instead of using border color uses clamp to zero. I can see why, because older versions of macOS (pre 10.12) and iOS (pre 14.0) had no support for border color. However, that has changed since and so I think adding the following code to renderer_mtl.mm (in getSamplerState) would bring this platform into parity with the others when able to do so (this might allow for clamp to white and options to be eventually exposed):

// On supported OS targets, clamp to zero can be replaced with border color
if ( @available(macOS 10.12, ios 14.0, *) )
{
	if ( m_samplerDescriptor.sAddressMode == MTLSamplerAddressModeClampToZero ) m_samplerDescriptor.sAddressMode = MTLSamplerAddressModeClampToBorderColor;
	if ( m_samplerDescriptor.tAddressMode == MTLSamplerAddressModeClampToZero ) m_samplerDescriptor.tAddressMode = MTLSamplerAddressModeClampToBorderColor;
	if ( m_samplerDescriptor.rAddressMode == MTLSamplerAddressModeClampToZero ) m_samplerDescriptor.rAddressMode = MTLSamplerAddressModeClampToBorderColor;
	m_samplerDescriptor.borderColor = MTLSamplerBorderColorTransparentBlack;
}

As for opaque black vs transparent black, I think transparent black is more useful overall, since you can use that to mask out of range render target reads without shader style tests like uv == saturate( uv ) etc.