Constexpr samplers are defined as local variables,
but were treated as held within an argument buffer.
- CompilerMSL::to_sampler_expression() support constexpr samplers
when using argument buffers, plus refactor to minimize generating
expression text that may not be used.
- Handle padding around multi-plane images that require multiple textures.
Only check for padding on the first plane, but include plane count in
total argument buffer slots consumed.
Metal writes to the depth/stencil attachment before fragment
shader execution if the execution does not modify the depth
value. However, Vulkan expects the write to happen after
fragment shader execution. To circumvent the issue we add
a simple depth passthrough if the user opts in. Only
required when the depth/stencil attachment is used as
input attachment at the same time. It seems Metal does not
correctly detect the dependency.
When targeting Vulkan semantics, we should emit code that is actually
readable.
Also, make sure to use plain F{Min,Max,Clamp} on HLSL. HLSL has
NaN-aware semantics by default.
Metal will incorrectly discard fragments with side effects under
certain circumstances prematurely. The conditions are the following:
- Fragment will always be discarded after side effect operation
- Pre fragment depth fails
- Modifies depth value for a constant value in the fragment shader.
This constant value will also fail the depth test.
However, Metal will also discard the fragment even if it has
operations with side effects inside the fragment shader before the
discard operation.
Vulkan states the graphics pipeline to execute in the following
order:
- Pre fragment depth test (cannot discard here due to modifying
depth value in fragment shader)
- Fragment shader (where the depth is modified and fragment
discarded)
- Post fragment depth test
Therefore, we need to enforce fragment shader execution and not
let Metal discard the fragment before that for such cases. This
change adds an option to provide such utility.
Inner function calls can contain flow-control sensitive code.
In this case, the function call itself must inherit the
control-dependence.
Rarely happens in practice since optimized code with SSA tends to
inline.
This adds support for bindings which share the same DescriptorSet/Binding pair.
The motivating example is vkd3d, which uses overlapping arrays of resources to
emulate D3D12 descriptor tables. The generated MSL argument buffer only
includes the first resource (in this example 't0'):
struct spvDescriptorSetBuffer2
{
array<texture2d<float>, 499968> t0 [[id(0)]];
// Overlapping binding: array<texture3d<float>, 499968> t2 [[id(0)]];
};
When t2 is referenced, we cast the instantiated member:
float4 r1 = spvDescriptorSet2.t0[_79].sample(...);
float4 r2 = (*(constant array<texture3d<float>, 499968>*)&spvDescriptorSet2.t0)[_97].sample(...);
Comment claims we can't, but I tested a number of older Metal compilers (Xcode 8 targeting macOS 10.11, macOS 10.13 online compiler, Xcode 14 targeting iOS 8) and none of them had any issues with it