Skip to content

Commit 73cf468

Browse files
committed
op: Implement 'filter_mode,minFilter' test in filter_mode.spec.ts
This PR adds a new test to ensure that the operation of minFilter works as expected. Issue: #2023
1 parent 5daf3ca commit 73cf468

File tree

1 file changed

+160
-1
lines changed

1 file changed

+160
-1
lines changed

src/webgpu/api/operation/sampling/filter_mode.spec.ts

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,164 @@ TODO:
1010

1111
import { makeTestGroup } from '../../../../common/framework/test_group.js';
1212
import { GPUTest } from '../../../gpu_test.js';
13+
import { TexelView } from '../../../util/texture/texel_view.js';
14+
import { textureContentIsOKByT2B } from '../../../util/texture/texture_ok.js';
1315

14-
export const g = makeTestGroup(GPUTest);
16+
class FilterModeTest extends GPUTest {
17+
createRenderPipelineForTest(): GPURenderPipeline {
18+
return this.device.createRenderPipeline({
19+
layout: 'auto',
20+
vertex: {
21+
module: this.device.createShaderModule({
22+
code: `
23+
struct Outputs {
24+
@builtin(position) Position : vec4<f32>,
25+
@location(0) fragUV : vec2<f32>,
26+
};
27+
28+
@vertex fn main(
29+
@builtin(vertex_index) VertexIndex : u32) -> Outputs {
30+
var position : array<vec3<f32>, 6> = array<vec3<f32>, 6>(
31+
vec3<f32>(-0.5, 0.5, -0.5),
32+
vec3<f32>(0.5, 0.5, -0.5),
33+
vec3<f32>(-0.5, 0.5, 0.5),
34+
vec3<f32>(-0.5, 0.5, 0.5),
35+
vec3<f32>(0.5, 0.5, -0.5),
36+
vec3<f32>(0.5, 0.5, 0.5));
37+
38+
// uv is pre-scaled to mimic repeating tiled texture
39+
var uv : array<vec2<f32>, 6> = array<vec2<f32>, 6>(
40+
vec2<f32>(0.0, 0.0),
41+
vec2<f32>(1.0, 0.0),
42+
vec2<f32>(0.0, 50.0),
43+
vec2<f32>(0.0, 50.0),
44+
vec2<f32>(1.0, 0.0),
45+
vec2<f32>(1.0, 50.0));
46+
47+
// draw a slanted plane in a specific way
48+
let matrix : mat4x4<f32> = mat4x4<f32>(
49+
vec4<f32>(-1.7320507764816284, 1.8322050568049563e-16, -6.176817699518044e-17, -6.170640314703498e-17),
50+
vec4<f32>(-2.1211504944260596e-16, -1.496108889579773, 0.5043753981590271, 0.5038710236549377),
51+
vec4<f32>(0.0, -43.63650894165039, -43.232173919677734, -43.18894577026367),
52+
vec4<f32>(0.0, 21.693578720092773, 21.789791107177734, 21.86800193786621));
53+
54+
var output : Outputs;
55+
output.fragUV = uv[VertexIndex];
56+
output.Position = matrix * vec4<f32>(position[VertexIndex], 1.0);
57+
return output;
58+
}
59+
`,
60+
}),
61+
entryPoint: 'main',
62+
},
63+
fragment: {
64+
module: this.device.createShaderModule({
65+
code: `
66+
@group(0) @binding(0) var sampler0 : sampler;
67+
@group(0) @binding(1) var texture0 : texture_2d<f32>;
68+
69+
@fragment fn main(
70+
@builtin(position) FragCoord : vec4<f32>,
71+
@location(0) fragUV: vec2<f32>)
72+
-> @location(0) vec4<f32> {
73+
return textureSample(texture0, sampler0, fragUV);
74+
}
75+
`,
76+
}),
77+
entryPoint: 'main',
78+
targets: [{ format: 'rgba8unorm' }],
79+
},
80+
primitive: { topology: 'triangle-list' },
81+
});
82+
}
83+
84+
createBindGroupForTest(
85+
layout: GPUBindGroupLayout,
86+
textureView: GPUTextureView,
87+
sampler: GPUSampler
88+
): GPUBindGroup {
89+
return this.device.createBindGroup({
90+
layout,
91+
entries: [
92+
{ binding: 0, resource: sampler },
93+
{ binding: 1, resource: textureView },
94+
],
95+
});
96+
}
97+
98+
drawTriangle(textureView: GPUTextureView, sampler: GPUSampler) {
99+
const renderTargetFormat = 'rgba8unorm';
100+
const renderTarget = this.device.createTexture({
101+
format: renderTargetFormat,
102+
size: { width: 2, height: 2, depthOrArrayLayers: 1 },
103+
usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
104+
});
105+
106+
const encoder = this.device.createCommandEncoder();
107+
const pass = encoder.beginRenderPass({
108+
colorAttachments: [
109+
{
110+
view: renderTarget.createView(),
111+
storeOp: 'store',
112+
loadOp: 'load',
113+
},
114+
],
115+
});
116+
117+
const testPipeline = this.createRenderPipelineForTest();
118+
pass.setPipeline(testPipeline);
119+
pass.setBindGroup(
120+
0,
121+
this.createBindGroupForTest(testPipeline.getBindGroupLayout(0), textureView, sampler)
122+
);
123+
pass.draw(6);
124+
125+
pass.end();
126+
this.device.queue.submit([encoder.finish()]);
127+
128+
const expColor = {
129+
R: 0,
130+
G: 0,
131+
B: 0,
132+
A: 0.0,
133+
};
134+
const expTexelView = TexelView.fromTexelsAsColors(renderTargetFormat, coords => expColor);
135+
136+
const result = textureContentIsOKByT2B(
137+
this,
138+
{ texture: renderTarget },
139+
[2, 2],
140+
{ expTexelView },
141+
{ maxDiffULPsForNormFormat: 1 }
142+
);
143+
this.eventualExpectOK(result);
144+
this.trackForCleanup(renderTarget);
145+
}
146+
}
147+
148+
export const g = makeTestGroup(FilterModeTest);
149+
150+
const kTextureFormat = 'rgba8unorm';
151+
152+
g.test('filter_mode,minFilter')
153+
.desc('Test that stencil reference is initialized as zero for new render pass.')
154+
.params(u => u.combine('magFilter', ['nearest', 'linear'] as const))
155+
.fn(async t => {
156+
const { magFilter } = t.params;
157+
158+
const textureSize = 2;
159+
const texture = t.device.createTexture({
160+
mipLevelCount: 1,
161+
size: { width: textureSize, height: textureSize, depthOrArrayLayers: 1 },
162+
format: kTextureFormat,
163+
usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING,
164+
});
165+
166+
const sampler = t.device.createSampler({
167+
magFilter,
168+
minFilter: 'linear',
169+
mipmapFilter: 'linear',
170+
});
171+
172+
t.drawTriangle(texture.createView(), sampler);
173+
});

0 commit comments

Comments
 (0)