mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-12-15 08:03:30 -08:00
Those tests are meant to check that each single sample computes the right value during a multi-sampled rendering operation. Checking whether the result is correct after multi-sample resolution isn't enough, because errors at different samples belonging to the same pixel might have cancelled out. Instead, for each shader invocation we compute the expected result and return the absolute value of the difference between the expected and computed value. This way errors at different samples cannot cancel out, but add up.
450 lines
14 KiB
Plaintext
450 lines
14 KiB
Plaintext
[require]
|
|
shader model >= 5.0
|
|
|
|
[input layout]
|
|
0 r32g32-float attr_centroid
|
|
|
|
[vb 0]
|
|
1.0 2.0
|
|
1.0 2.0
|
|
1.0 2.0
|
|
|
|
[rtv 0]
|
|
format r32g32b32a32-float
|
|
size (2dms, 4, 640, 480)
|
|
|
|
[vertex shader]
|
|
% The pixels in the leftmost column lose their leftmost sample.
|
|
static const float epsilon = 0.25f * 2.0f / 640.0f;
|
|
static const float2 vertices[3] =
|
|
{
|
|
{-1.0f + epsilon, 1.0f},
|
|
{ 3.0f, 1.0f},
|
|
{-1.0f + epsilon, -3.0f},
|
|
};
|
|
|
|
void main(uint id : SV_VertexID, out float4 position : SV_Position, out float2 attr : ATTR,
|
|
inout float2 attr2 : ATTR_centroid0)
|
|
{
|
|
position = float4(vertices[id], 0.0f, 1.0f);
|
|
attr = float2(position.x * 320.0f + 320.0f, -position.y * 240.0f + 240.0f);
|
|
}
|
|
|
|
% The multiplication by (sample_idx + 1) when computing the error is to
|
|
% introduce a dependency on the sample index which hopefully the compiler is not
|
|
% able to optimize; this way the shader is hopefully forced to execute for each
|
|
% sample. These tests depend on the implementation using the default sample
|
|
% positions.
|
|
|
|
% First let's check that we're getting the position interpolation right:
|
|
% center interpolation.
|
|
|
|
[pixel shader]
|
|
float4 main(float4 pos : SV_Position, uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float2 diff = pos.xy - ref;
|
|
float2 err = abs(diff) * (sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
todo(msl & sm>=6) draw triangle list 3
|
|
todo(vulkan | opengl & llvmpipe | d3d12) probe ( 0, 0) f32(0.25, 0.25, 0.25, 0.25)
|
|
todo(vulkan | opengl & llvmpipe | d3d12) probe (639, 0) f32(0.0, 0.0, 0.0, 0.0)
|
|
todo(vulkan | opengl & llvmpipe | d3d12) probe ( 0, 479) f32(0.25, 0.25, 0.25, 0.25)
|
|
todo(vulkan | opengl & llvmpipe | d3d12) probe (639, 479) f32(0.0, 0.0, 0.0, 0.0)
|
|
|
|
% Centroid interpolation, which means the pixel center if all samples are
|
|
% covered and the first covered sample if a least a sample is not covered (in
|
|
% general it has nothing to do with the actual centroid of the covered samples).
|
|
% The WARP driver seems to have problems with some corner pixels, which we
|
|
% avoid.
|
|
|
|
[pixel shader fail]
|
|
static const float2 positions[4] =
|
|
{
|
|
{-0.125f, -0.375f},
|
|
{ 0.375f, -0.125f},
|
|
{-0.375f, 0.125f},
|
|
{ 0.125f, 0.375f},
|
|
};
|
|
|
|
float4 main(float4 pos : SV_Position_centroid, uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
bool first_col = floor(pos.x) == 0.0f;
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float2 diff = pos.xy - ref;
|
|
float2 expected = first_col ? positions[0] : 0.0f;
|
|
float2 err = abs(diff - expected) * (sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
[pixel shader]
|
|
static const float2 positions[4] =
|
|
{
|
|
{-0.125f, -0.375f},
|
|
{ 0.375f, -0.125f},
|
|
{-0.375f, 0.125f},
|
|
{ 0.125f, 0.375f},
|
|
};
|
|
float4 main(centroid float4 pos : SV_Position, uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
bool first_col = floor(pos.x) == 0.0f;
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float2 diff = pos.xy - ref;
|
|
float2 expected = first_col ? positions[0] : 0.0f;
|
|
float2 err = abs(diff - expected) * (sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
todo(glsl | msl & sm>=6) draw triangle list 3
|
|
todo probe ( 0, 0) f32(0.25, 0.25, 0.25, 0.25)
|
|
todo(vulkan | opengl & llvmpipe | d3d12) probe (638, 0) f32(0.0, 0.0, 0.0, 0.0)
|
|
todo probe ( 0, 478) f32(0.25, 0.25, 0.25, 0.25)
|
|
todo(vulkan | opengl & llvmpipe | d3d12) probe (639, 479) f32(0.0, 0.0, 0.0, 0.0)
|
|
|
|
% Sample interpolation.
|
|
|
|
[pixel shader todo]
|
|
static const float2 positions[4] =
|
|
{
|
|
{-0.125f, -0.375f},
|
|
{ 0.375f, -0.125f},
|
|
{-0.375f, 0.125f},
|
|
{ 0.125f, 0.375f},
|
|
};
|
|
float4 main(sample float4 pos : SV_Position, uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float2 diff = pos.xy - ref;
|
|
float2 err = abs(diff - positions[sample_idx]) * (sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
todo(sm<6 | msl) draw triangle list 3
|
|
probe ( 0, 0) rgba(0.25, 0.25, 0.25, 0.25)
|
|
probe (639, 0) rgba(0.0, 0.0, 0.0, 0.0)
|
|
probe ( 0, 479) rgba(0.25, 0.25, 0.25, 0.25)
|
|
probe (639, 479) rgba(0.0, 0.0, 0.0, 0.0)
|
|
|
|
% Same tests with a non-SV semantic: pixel center interpolation.
|
|
|
|
[pixel shader]
|
|
float4 main(float4 pos : SV_Position, float2 attr : ATTR, uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float2 diff = attr.xy - ref;
|
|
float2 err = abs(diff) * (sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
todo(msl & sm>=6) draw triangle list 3
|
|
probe ( 0, 0) rgba(0.25, 0.25, 0.25, 0.25)
|
|
probe (639, 0) rgba(0.0, 0.0, 0.0, 0.0)
|
|
probe ( 0, 479) rgba(0.25, 0.25, 0.25, 0.25)
|
|
probe (639, 479) rgba(0.0, 0.0, 0.0, 0.0)
|
|
|
|
% Centroid interpolation, which means the pixel center if all samples are
|
|
% covered and the first covered sample if a least a sample is not covered (in
|
|
% general it has nothing to do with the actual centroid of the covered samples).
|
|
% The WARP driver seems to have problems with some corner pixels, which we
|
|
% avoid.
|
|
%
|
|
% Since Vulkan has more relaxed specification for centroid interpolation than
|
|
% D3D12, not all drivers implement the behavior we need. llvmpipe is one of
|
|
% those, so is marked todo.
|
|
|
|
[pixel shader]
|
|
static const float2 positions[4] =
|
|
{
|
|
{-0.125f, -0.375f},
|
|
{ 0.375f, -0.125f},
|
|
{-0.375f, 0.125f},
|
|
{ 0.125f, 0.375f},
|
|
};
|
|
|
|
float4 main(float4 pos : SV_Position, centroid float2 attr : ATTR,
|
|
uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
bool first_col = floor(pos.x) == 0.0f;
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float2 diff = attr.xy - ref;
|
|
float2 expected = first_col ? positions[0] : 0.0f;
|
|
float2 err = abs(diff - expected) * (sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
todo(glsl | msl) draw triangle list 3
|
|
todo(llvmpipe) probe (0, 0) rgba(0.25, 0.25, 0.25, 0.25)
|
|
probe (638, 0) rgba(0.0, 0.0, 0.0, 0.0)
|
|
probe (0, 478) rgba(0.25, 0.25, 0.25, 0.25)
|
|
todo(llvmpipe) probe (639, 479) rgba(0.0, 0.0, 0.0, 0.0)
|
|
|
|
[pixel shader]
|
|
static const float2 positions[4] =
|
|
{
|
|
{-0.125f, -0.375f},
|
|
{ 0.375f, -0.125f},
|
|
{-0.375f, 0.125f},
|
|
{ 0.125f, 0.375f},
|
|
};
|
|
|
|
float4 main(float4 pos : SV_Position, float2 attr : ATTR_centRoid,
|
|
uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
bool first_col = floor(pos.x) == 0.0f;
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float2 diff = attr.xy - ref;
|
|
float2 expected = first_col ? positions[0] : 0.0f;
|
|
float2 err = abs(diff - expected) * (sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
% Tests are skipped for sm6, since it doesn't consider semantic suffixes
|
|
% leaving names unchanged.
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
if(sm<6) todo(msl | glsl) draw triangle list 3
|
|
if(sm<6) todo(llvmpipe) probe (0, 0) f32(0.25, 0.25, 0.25, 0.25)
|
|
if(sm<6) probe (638, 0) f32(0.0, 0.0, 0.0, 0.0)
|
|
if(sm<6) probe (0, 478) f32(0.25, 0.25, 0.25, 0.25)
|
|
if(sm<6) todo(llvmpipe) probe (639, 479) f32(0.0, 0.0, 0.0, 0.0)
|
|
|
|
% The "_centroid" semantic modifier can be specified together with the "centroid" prefix attribute.
|
|
|
|
[pixel shader]
|
|
static const float2 positions[4] =
|
|
{
|
|
{-0.125f, -0.375f},
|
|
{ 0.375f, -0.125f},
|
|
{-0.375f, 0.125f},
|
|
{ 0.125f, 0.375f},
|
|
};
|
|
|
|
float4 main(float4 pos : SV_Position, centroid float2 attr : ATTR_centRoid,
|
|
uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
bool first_col = floor(pos.x) == 0.0f;
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float2 diff = attr.xy - ref;
|
|
float2 expected = first_col ? positions[0] : 0.0f;
|
|
float2 err = abs(diff - expected) * (sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
% Tests are skipped for sm6, since it doesn't consider semantic suffixes
|
|
% leaving names unchanged.
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
if(sm<6) todo(msl | glsl) draw triangle list 3
|
|
if(sm<6) todo(llvmpipe) probe (0, 0) f32(0.25, 0.25, 0.25, 0.25)
|
|
if(sm<6) probe (638, 0) f32(0.0, 0.0, 0.0, 0.0)
|
|
if(sm<6) probe (0, 478) f32(0.25, 0.25, 0.25, 0.25)
|
|
if(sm<6) todo(llvmpipe) probe (639, 479) f32(0.0, 0.0, 0.0, 0.0)
|
|
|
|
[pixel shader]
|
|
static const float2 positions[4] =
|
|
{
|
|
{-0.125f, -0.375f},
|
|
{ 0.375f, -0.125f},
|
|
{-0.375f, 0.125f},
|
|
{ 0.125f, 0.375f},
|
|
};
|
|
|
|
struct ps_in
|
|
{
|
|
float4 pos : SV_Position;
|
|
float2 attr : ATTR_centRoid;
|
|
uint sample_idx : SV_SampleIndex;
|
|
};
|
|
|
|
float4 main(ps_in data) : SV_Target
|
|
{
|
|
bool first_col = floor(data.pos.x) == 0.0f;
|
|
float2 ref = floor(data.pos.xy) + float2(0.5f, 0.5f);
|
|
float2 diff = data.attr.xy - ref;
|
|
float2 expected = first_col ? positions[0] : 0.0f;
|
|
float2 err = abs(diff - expected) * (data.sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
% Tests are skipped for sm6, since it doesn't consider semantic suffixes
|
|
% leaving names unchanged.
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
if(sm<6) todo(msl | glsl) draw triangle list 3
|
|
if(sm<6) todo(llvmpipe) probe (0, 0) f32(0.25, 0.25, 0.25, 0.25)
|
|
if(sm<6) probe (638, 0) f32(0.0, 0.0, 0.0, 0.0)
|
|
if(sm<6) probe (0, 478) f32(0.25, 0.25, 0.25, 0.25)
|
|
if(sm<6) todo(llvmpipe) probe (639, 479) f32(0.0, 0.0, 0.0, 0.0)
|
|
|
|
[pixel shader]
|
|
float4 main(float4 pos : SV_Position, float2 attr : ATTR, float2 attr2 : ATTR_centroid0,
|
|
uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float4 diff = float4(attr.xy - ref, attr2);
|
|
float4 expected = float4(0.0f, 0.0f, 1.0f, 2.0f);
|
|
float4 err = abs(diff - expected) * (sample_idx + 1);
|
|
return floor(1000.0f * err);
|
|
}
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
todo(msl & sm>=6) draw triangle list 3
|
|
probe (0, 0) f32(0.25, 0.25, 0.25, 0.25)
|
|
probe (638, 0) f32(0.0, 0.0, 0.0, 0.0)
|
|
probe (0, 478) f32(0.25, 0.25, 0.25, 0.25)
|
|
probe (639, 479) f32(0.0, 0.0, 0.0, 0.0)
|
|
|
|
[pixel shader]
|
|
float4 main(float4 pos : SV_Position, float2 attr : ATTR, float2 attr2 : ATTR_centroid_centroid,
|
|
uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
return float4(attr2, 0.0f, 0.0f);
|
|
}
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
% This test causes the GPU to hang with MVK.
|
|
if(sm<6 & !mvk) todo(msl | glsl) draw triangle list 3
|
|
if(sm<6 & !mvk) todo probe (0, 0) f32(1.0, 1.75, 0.25, 0.25)
|
|
if(sm<6 & !mvk) todo probe (638, 0) f32(1.0, 2.0, 0.0, 0.0)
|
|
|
|
% Sample interpolation.
|
|
|
|
[pixel shader todo]
|
|
static const float2 positions[4] =
|
|
{
|
|
{-0.125f, -0.375f},
|
|
{ 0.375f, -0.125f},
|
|
{-0.375f, 0.125f},
|
|
{ 0.125f, 0.375f},
|
|
};
|
|
float4 main(float4 pos : SV_Position, sample float2 attr : ATTR,
|
|
uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float2 diff = attr.xy - ref;
|
|
float2 err = abs(diff - positions[sample_idx]) * (sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
todo(sm<6 | msl) draw triangle list 3
|
|
probe ( 0, 0) rgba(0.25, 0.25, 0.25, 0.25)
|
|
probe (639, 0) rgba(0.0, 0.0, 0.0, 0.0)
|
|
probe ( 0, 479) rgba(0.25, 0.25, 0.25, 0.25)
|
|
probe (639, 479) rgba(0.0, 0.0, 0.0, 0.0)
|
|
|
|
% Using EvaluateAttributeCentroid().
|
|
|
|
[pixel shader todo]
|
|
static const float2 positions[4] =
|
|
{
|
|
{-0.125f, -0.375f},
|
|
{ 0.375f, -0.125f},
|
|
{-0.375f, 0.125f},
|
|
{ 0.125f, 0.375f},
|
|
};
|
|
float4 main(float4 pos : SV_Position, float2 attr : ATTR,
|
|
uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
bool first_col = floor(pos.x) == 0.0f;
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float2 eval = EvaluateAttributeCentroid(attr);
|
|
float2 diff = eval.xy - ref;
|
|
float2 expected = first_col ? positions[0] : 0.0f;
|
|
float2 err = abs(diff - expected) * (sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
todo(sm<6 | msl) draw triangle list 3
|
|
todo(llvmpipe) probe ( 0, 0) rgba(0.25, 0.25, 0.25, 0.25)
|
|
probe (638, 0) rgba(0.0, 0.0, 0.0, 0.0)
|
|
probe ( 0, 478) rgba(0.25, 0.25, 0.25, 0.25)
|
|
todo(llvmpipe) probe (639, 479) rgba(0.0, 0.0, 0.0, 0.0)
|
|
|
|
% Using EvaluateAttributeAtSample().
|
|
|
|
[pixel shader todo]
|
|
static const float2 positions[4] =
|
|
{
|
|
{-0.125f, -0.375f},
|
|
{ 0.375f, -0.125f},
|
|
{-0.375f, 0.125f},
|
|
{ 0.125f, 0.375f},
|
|
};
|
|
static const uint mixer[4] = {1, 3, 2, 0};
|
|
float4 main(float4 pos : SV_Position, float2 attr : ATTR,
|
|
uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
/* Use a different sample index than the one we're evaluating, just in case
|
|
* the compiler tries to cheat and do a plain sample interpolation instead
|
|
* of using the specific sample we requested. */
|
|
float2 eval;
|
|
/* Older WARP versions do not like calling EvaluateAttributeAtSample() on
|
|
* anything that is not an immediate constant. */
|
|
switch (mixer[sample_idx])
|
|
{
|
|
case 0: eval = EvaluateAttributeAtSample(attr, 0); break;
|
|
case 1: eval = EvaluateAttributeAtSample(attr, 1); break;
|
|
case 2: eval = EvaluateAttributeAtSample(attr, 2); break;
|
|
case 3: eval = EvaluateAttributeAtSample(attr, 3); break;
|
|
}
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float2 diff = eval.xy - ref;
|
|
float2 err = abs(diff - positions[mixer[sample_idx]]) * (sample_idx + 1);
|
|
return floor(1000.0f * float4(err, 0.0f, 0.0f));
|
|
}
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
todo(sm<6 | msl) draw triangle list 3
|
|
probe ( 0, 0) rgba(0.25, 0.25, 0.25, 0.25)
|
|
probe (639, 0) rgba(0.0, 0.0, 0.0, 0.0)
|
|
probe ( 0, 479) rgba(0.25, 0.25, 0.25, 0.25)
|
|
probe (639, 479) rgba(0.0, 0.0, 0.0, 0.0)
|
|
|
|
[require]
|
|
shader model >= 6.0
|
|
|
|
% SM6 appears to require all vertex outputs to be declared in
|
|
% pixel shader, meaning that both ATTR and ATTR_centroid must be present.
|
|
% That is not going to work for <SM6, so it's tested separately.
|
|
|
|
[pixel shader]
|
|
float4 main(float4 pos : SV_Position, float2 attr : ATTR,
|
|
float2 attr2 : ATTR_centroid, uint sample_idx : SV_SampleIndex) : SV_Target
|
|
{
|
|
float2 ref = floor(pos.xy) + float2(0.5f, 0.5f);
|
|
float4 diff = float4(attr.xy - ref, attr2);
|
|
float4 expected = float4(0.0f, 0.0f, 1.0f, 2.0f);
|
|
float4 err = abs(diff - expected) * (sample_idx + 1);
|
|
return floor(1000.0f * err);
|
|
}
|
|
|
|
[test]
|
|
clear rtv 0 1.0 1.0 1.0 1.0
|
|
todo(glsl | msl) draw triangle list 3
|
|
probe (0, 0) f32(0.25, 0.25, 0.25, 0.25)
|
|
probe (638, 0) f32(0.0, 0.0, 0.0, 0.0)
|
|
probe (0, 478) f32(0.25, 0.25, 0.25, 0.25)
|
|
probe (639, 479) f32(0.0, 0.0, 0.0, 0.0)
|