Skip to content

Commit 14ca630

Browse files
committed
Test that mismatching swizzles cause validation error in compat mode
1 parent d3df092 commit 14ca630

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

src/webgpu/api/validation/capability_checks/features/texture_component_swizzle.spec.ts

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { UniqueFeaturesOrLimitsGPUTest } from '../../../../gpu_test.js';
1414
import {
1515
isIdentitySwizzle,
1616
kSwizzleTests,
17+
swizzlesAreTheSame,
1718
swizzleSpecToGPUTextureComponentSwizzle,
1819
} from './texture_component_swizzle_utils.js';
1920

@@ -80,3 +81,120 @@ g.test('no_render_nor_storage')
8081
texture.createView({ swizzle });
8182
}, shouldError);
8283
});
84+
85+
g.test('compatibility_mode')
86+
.desc(
87+
`
88+
Test that in compatibility mode, swizzles must be equivalent.
89+
`
90+
)
91+
.beforeAllSubcases(t => {
92+
// MAINTENANCE_TODO: Remove this cast once texture-component-swizzle is added to @webgpu/types
93+
t.selectDeviceOrSkipTestCase('texture-component-swizzle' as GPUFeatureName);
94+
})
95+
.params(u =>
96+
u
97+
.beginSubcases()
98+
.combine('swizzleSpec', kSwizzleTests)
99+
.combine('otherSwizzleSpec', kSwizzleTests)
100+
.combine('pipelineType', ['render', 'compute'] as const)
101+
)
102+
.fn(t => {
103+
const { swizzleSpec, otherSwizzleSpec, pipelineType } = t.params;
104+
const swizzle = swizzleSpecToGPUTextureComponentSwizzle(swizzleSpec);
105+
const otherSwizzle = swizzleSpecToGPUTextureComponentSwizzle(otherSwizzleSpec);
106+
107+
const module = t.device.createShaderModule({
108+
code: `
109+
@group(0) @binding(0) var tex0: texture_2d<f32>;
110+
@group(1) @binding(0) var tex1: texture_2d<f32>;
111+
112+
@compute @workgroup_size(1) fn cs() {
113+
_ = tex0;
114+
_ = tex1;
115+
}
116+
117+
@vertex fn vs() -> @builtin(position) vec4f {
118+
return vec4f(0);
119+
}
120+
121+
@fragment fn fs() -> @location(0) vec4f {
122+
_ = tex0;
123+
_ = tex1;
124+
return vec4f(0);
125+
}
126+
`,
127+
});
128+
129+
const pipeline =
130+
pipelineType === 'compute'
131+
? t.device.createComputePipeline({
132+
layout: 'auto',
133+
compute: { module },
134+
})
135+
: t.device.createRenderPipeline({
136+
layout: 'auto',
137+
vertex: { module },
138+
fragment: { module, targets: [{ format: 'rgba8unorm' }] },
139+
});
140+
141+
const texture = t.createTextureTracked({
142+
size: [1],
143+
format: 'rgba8unorm',
144+
usage: GPUTextureUsage.TEXTURE_BINDING,
145+
});
146+
147+
const bindGroup0 = t.device.createBindGroup({
148+
layout: pipeline.getBindGroupLayout(0),
149+
entries: [
150+
{
151+
binding: 0,
152+
resource: texture.createView({ swizzle }),
153+
},
154+
],
155+
});
156+
157+
const bindGroup1 = t.device.createBindGroup({
158+
layout: pipeline.getBindGroupLayout(0),
159+
entries: [
160+
{
161+
binding: 0,
162+
resource: texture.createView({ swizzle: otherSwizzle }),
163+
},
164+
],
165+
});
166+
167+
const encoder = t.device.createCommandEncoder();
168+
switch (pipelineType) {
169+
case 'compute': {
170+
const pass = encoder.beginComputePass();
171+
pass.setPipeline(pipeline as GPUComputePipeline);
172+
pass.setBindGroup(0, bindGroup0);
173+
pass.setBindGroup(1, bindGroup1);
174+
pass.dispatchWorkgroups(1);
175+
pass.end();
176+
break;
177+
}
178+
case 'render': {
179+
const view = t.createTextureTracked({
180+
size: [1],
181+
format: 'rgba8unorm',
182+
usage: GPUTextureUsage.RENDER_ATTACHMENT,
183+
});
184+
const pass = encoder.beginRenderPass({
185+
colorAttachments: [{ view, loadOp: 'clear', storeOp: 'store' }],
186+
});
187+
pass.setPipeline(pipeline as GPURenderPipeline);
188+
pass.setBindGroup(0, bindGroup0);
189+
pass.setBindGroup(1, bindGroup1);
190+
pass.draw(3);
191+
pass.end();
192+
}
193+
}
194+
195+
const shouldError = t.isCompatibility && !swizzlesAreTheSame(swizzle, otherSwizzle);
196+
197+
t.expectValidationError(() => {
198+
encoder.finish();
199+
}, shouldError);
200+
});

0 commit comments

Comments
 (0)