Skip to content

Commit 9317e7c

Browse files
committed
webgpu/api/validation: Fix vertex_shader_input_location_limit test
Shader compilation / validation will fail for vertex attributes that are out of bounds.
1 parent afbdb6d commit 9317e7c

File tree

1 file changed

+40
-19
lines changed

1 file changed

+40
-19
lines changed

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

+40-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,10 @@ g.test('vertex_shader_input_location_limit')
396413
},
397414
];
398415

399-
const success = testLocation < kMaxVertexAttributes;
416+
const success = {
417+
shader: testLocation >= 0 && testLocation < kMaxVertexAttributes,
418+
pipeline: testLocation >= 0 && testLocation < kMaxVertexAttributes,
419+
};
400420
t.testVertexState(success, vertexBuffers, shader);
401421
});
402422

@@ -438,14 +458,15 @@ g.test('vertex_shader_input_location_in_vertex_state')
438458
extraAttributeCount,
439459
extraAttributeSkippedLocations: [testShaderLocation],
440460
});
441-
t.testVertexState(false, vertexBuffers, shader);
461+
462+
t.testVertexState({ shader: true, pipeline: false }, vertexBuffers, shader);
442463

443464
// Add an attribute for the test location and try again.
444465
addTestAttributes(attributes, {
445466
testAttribute: { format: 'float32', shaderLocation: testShaderLocation, offset: 0 },
446467
testAttributeAtStart,
447468
});
448-
t.testVertexState(true, vertexBuffers, shader);
469+
t.testVertexState({ shader: true, pipeline: true }, vertexBuffers, shader);
449470
});
450471

451472
g.test('vertex_shader_type_matches_attribute_format')
@@ -484,7 +505,7 @@ g.test('vertex_shader_type_matches_attribute_format')
484505
float: 'f32',
485506
}[kVertexFormatInfo[format].type];
486507

487-
const success = requiredBaseType === shaderBaseType;
508+
const success = { shader: true, pipeline: requiredBaseType === shaderBaseType };
488509
t.testVertexState(
489510
success,
490511
[
@@ -554,7 +575,7 @@ g.test('vertex_attribute_offset_alignment')
554575

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

559580
t.testVertexState(success, vertexBuffers);
560581
});
@@ -628,7 +649,7 @@ g.test('vertex_attribute_contained_in_stride')
628649
const formatSize = formatInfo.bytesPerComponent * formatInfo.componentCount;
629650
const limit = arrayStride === 0 ? kMaxVertexBufferArrayStride : arrayStride;
630651

631-
const success = offset + formatSize <= limit;
652+
const success = { shader: true, pipeline: offset + formatSize <= limit };
632653
t.testVertexState(success, vertexBuffers);
633654
});
634655

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

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

0 commit comments

Comments
 (0)