Skip to content

Commit cd2eac6

Browse files
committed
webgpu/api/validation: Fix vertex_shader_input_location_limit test
The WGSL spec states that the `[[location(n)]]` decoration must be a "non-negative i32 literal".
1 parent 6ff5dc6 commit cd2eac6

File tree

1 file changed

+43
-19
lines changed

1 file changed

+43
-19
lines changed

src/webgpu/api/validation/vertex_state.spec.ts

+43-19
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,31 @@ class F extends ValidationTest {
8383
}
8484

8585
testVertexState(
86-
success: boolean,
86+
success: { shader: boolean; pipeline: boolean },
8787
buffers: Iterable<GPUVertexBufferLayout>,
8888
vertexShader: string = VERTEX_SHADER_CODE_WITH_NO_INPUT
8989
) {
90-
const vsModule = this.device.createShaderModule({ code: vertexShader });
9190
const fsModule = this.device.createShaderModule({
9291
code: `
9392
[[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {
9493
return vec4<f32>(0.0, 1.0, 0.0, 1.0);
9594
}`,
9695
});
9796

97+
let vsModule: GPUShaderModule | undefined;
98+
99+
this.expectValidationError(() => {
100+
vsModule = this.device.createShaderModule({ code: vertexShader });
101+
}, !success.shader);
102+
103+
if (vsModule === undefined) {
104+
return;
105+
}
106+
98107
this.expectValidationError(() => {
99108
this.device.createRenderPipeline({
100109
vertex: {
101-
module: vsModule,
110+
module: vsModule as GPUShaderModule,
102111
entryPoint: 'main',
103112
buffers,
104113
},
@@ -109,7 +118,7 @@ class F extends ValidationTest {
109118
},
110119
primitive: { topology: 'triangle-list' },
111120
});
112-
}, !success);
121+
}, !success.pipeline);
113122
}
114123

115124
generateTestVertexShader(inputs: { type: string; location: number }[]): string {
@@ -164,7 +173,7 @@ g.test('max_vertex_buffer_limit')
164173
}
165174
}
166175

167-
const success = count <= kMaxVertexBuffers;
176+
const success = { shader: true, pipeline: count <= kMaxVertexBuffers };
168177
t.testVertexState(success, vertexBuffers);
169178
});
170179

@@ -201,7 +210,7 @@ g.test('max_vertex_attribute_limit')
201210
vertexBuffers.push({ arrayStride: 0, attributes });
202211
}
203212

204-
const success = attribCount <= kMaxVertexAttributes;
213+
const success = { shader: true, pipeline: attribCount <= kMaxVertexAttributes };
205214
t.testVertexState(success, vertexBuffers);
206215
});
207216

@@ -229,7 +238,7 @@ g.test('max_vertex_buffer_array_stride_limit')
229238
const vertexBuffers = [];
230239
vertexBuffers[vertexBufferIndex] = { arrayStride, attributes: [] };
231240

232-
const success = arrayStride <= kMaxVertexBufferArrayStride;
241+
const success = { shader: true, pipeline: arrayStride <= kMaxVertexBufferArrayStride };
233242
t.testVertexState(success, vertexBuffers);
234243
});
235244

@@ -258,7 +267,7 @@ g.test('vertex_buffer_array_stride_limit_alignment')
258267
const vertexBuffers = [];
259268
vertexBuffers[vertexBufferIndex] = { arrayStride, attributes: [] };
260269

261-
const success = arrayStride % 4 === 0;
270+
const success = { shader: true, pipeline: arrayStride % 4 === 0 };
262271
t.testVertexState(success, vertexBuffers);
263272
});
264273

@@ -295,7 +304,7 @@ g.test('vertex_attribute_shaderLocation_limit')
295304
const vertexBuffers = [];
296305
vertexBuffers[vertexBufferIndex] = { arrayStride: 256, attributes };
297306

298-
const success = testShaderLocation < kMaxVertexAttributes;
307+
const success = { shader: true, pipeline: testShaderLocation < kMaxVertexAttributes };
299308
t.testVertexState(success, vertexBuffers);
300309
});
301310

@@ -360,18 +369,26 @@ g.test('vertex_attribute_shaderLocation_unique')
360369

361370
// Note that an empty vertex shader will be used so errors only happens because of the conflict
362371
// in the vertex state.
363-
const success = shaderLocationA !== shaderLocationB;
372+
const success = { shader: true, pipeline: shaderLocationA !== shaderLocationB };
364373
t.testVertexState(success, vertexBuffers);
365374
});
366375

367376
g.test('vertex_shader_input_location_limit')
368377
.desc(
369378
`Test that vertex shader's input's location decoration must be less than maxVertexAttributes.
370-
- Test for shaderLocation 0, 1, limit - 1, limit`
379+
- Test for shaderLocation 0, 1, limit - 1, limit, -1, 0x7fffffff, 2 ** 32`
371380
)
372381
.paramsSubcasesOnly(u =>
373382
u //
374-
.combine('testLocation', [0, 1, kMaxVertexAttributes - 1, kMaxVertexAttributes, -1, 2 ** 32])
383+
.combine('testLocation', [
384+
0,
385+
1,
386+
kMaxVertexAttributes - 1,
387+
kMaxVertexAttributes,
388+
-1,
389+
0x7fffffff,
390+
2 ** 32,
391+
])
375392
)
376393
.fn(t => {
377394
const { testLocation } = t.params;
@@ -396,7 +413,13 @@ g.test('vertex_shader_input_location_limit')
396413
},
397414
];
398415

399-
const success = testLocation < kMaxVertexAttributes;
416+
const success = {
417+
// [[location(n)]] decoration must be a "non-negative i32 literal"
418+
// TODO: Dawn raises a "Attribute location (N) over limits" error at
419+
// shader creation time for N>15. Is this right?
420+
shader: testLocation >= 0 && testLocation < 0x7fffffff,
421+
pipeline: testLocation >= 0 && testLocation < kMaxVertexAttributes,
422+
};
400423
t.testVertexState(success, vertexBuffers, shader);
401424
});
402425

@@ -438,14 +461,15 @@ g.test('vertex_shader_input_location_in_vertex_state')
438461
extraAttributeCount,
439462
extraAttributeSkippedLocations: [testShaderLocation],
440463
});
441-
t.testVertexState(false, vertexBuffers, shader);
464+
465+
t.testVertexState({ shader: true, pipeline: false }, vertexBuffers, shader);
442466

443467
// Add an attribute for the test location and try again.
444468
addTestAttributes(attributes, {
445469
testAttribute: { format: 'float32', shaderLocation: testShaderLocation, offset: 0 },
446470
testAttributeAtStart,
447471
});
448-
t.testVertexState(true, vertexBuffers, shader);
472+
t.testVertexState({ shader: true, pipeline: true }, vertexBuffers, shader);
449473
});
450474

451475
g.test('vertex_shader_type_matches_attribute_format')
@@ -484,7 +508,7 @@ g.test('vertex_shader_type_matches_attribute_format')
484508
float: 'f32',
485509
}[kVertexFormatInfo[format].type];
486510

487-
const success = requiredBaseType === shaderBaseType;
511+
const success = { shader: true, pipeline: requiredBaseType === shaderBaseType };
488512
t.testVertexState(
489513
success,
490514
[
@@ -554,7 +578,7 @@ g.test('vertex_attribute_offset_alignment')
554578

555579
const formatInfo = kVertexFormatInfo[format];
556580
const formatSize = formatInfo.bytesPerComponent * formatInfo.componentCount;
557-
const success = offset % Math.min(4, formatSize) === 0;
581+
const success = { shader: true, pipeline: offset % Math.min(4, formatSize) === 0 };
558582

559583
t.testVertexState(success, vertexBuffers);
560584
});
@@ -628,7 +652,7 @@ g.test('vertex_attribute_contained_in_stride')
628652
const formatSize = formatInfo.bytesPerComponent * formatInfo.componentCount;
629653
const limit = arrayStride === 0 ? kMaxVertexBufferArrayStride : arrayStride;
630654

631-
const success = offset + formatSize <= limit;
655+
const success = { shader: true, pipeline: offset + formatSize <= limit };
632656
t.testVertexState(success, vertexBuffers);
633657
});
634658

@@ -642,5 +666,5 @@ g.test('many_attributes_overlapping')
642666
attributes.push({ format: formats[i % 3], offset: i * 4, shaderLocation: i } as const);
643667
}
644668

645-
t.testVertexState(true, [{ arrayStride: 0, attributes }]);
669+
t.testVertexState({ shader: true, pipeline: true }, [{ arrayStride: 0, attributes }]);
646670
});

0 commit comments

Comments
 (0)