Skip to content

Commit

Permalink
webgpu/api/validation: Fix vertex_shader_input_location_limit test
Browse files Browse the repository at this point in the history
The WGSL spec states that the `[[location(n)]]` decoration must be a "non-negative i32 literal".
  • Loading branch information
ben-clayton committed Sep 30, 2021
1 parent 6ff5dc6 commit cd2eac6
Showing 1 changed file with 43 additions and 19 deletions.
62 changes: 43 additions & 19 deletions src/webgpu/api/validation/vertex_state.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,22 +83,31 @@ class F extends ValidationTest {
}

testVertexState(
success: boolean,
success: { shader: boolean; pipeline: boolean },
buffers: Iterable<GPUVertexBufferLayout>,
vertexShader: string = VERTEX_SHADER_CODE_WITH_NO_INPUT
) {
const vsModule = this.device.createShaderModule({ code: vertexShader });
const fsModule = this.device.createShaderModule({
code: `
[[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {
return vec4<f32>(0.0, 1.0, 0.0, 1.0);
}`,
});

let vsModule: GPUShaderModule | undefined;

this.expectValidationError(() => {
vsModule = this.device.createShaderModule({ code: vertexShader });
}, !success.shader);

if (vsModule === undefined) {
return;
}

this.expectValidationError(() => {
this.device.createRenderPipeline({
vertex: {
module: vsModule,
module: vsModule as GPUShaderModule,
entryPoint: 'main',
buffers,
},
Expand All @@ -109,7 +118,7 @@ class F extends ValidationTest {
},
primitive: { topology: 'triangle-list' },
});
}, !success);
}, !success.pipeline);
}

generateTestVertexShader(inputs: { type: string; location: number }[]): string {
Expand Down Expand Up @@ -164,7 +173,7 @@ g.test('max_vertex_buffer_limit')
}
}

const success = count <= kMaxVertexBuffers;
const success = { shader: true, pipeline: count <= kMaxVertexBuffers };
t.testVertexState(success, vertexBuffers);
});

Expand Down Expand Up @@ -201,7 +210,7 @@ g.test('max_vertex_attribute_limit')
vertexBuffers.push({ arrayStride: 0, attributes });
}

const success = attribCount <= kMaxVertexAttributes;
const success = { shader: true, pipeline: attribCount <= kMaxVertexAttributes };
t.testVertexState(success, vertexBuffers);
});

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

const success = arrayStride <= kMaxVertexBufferArrayStride;
const success = { shader: true, pipeline: arrayStride <= kMaxVertexBufferArrayStride };
t.testVertexState(success, vertexBuffers);
});

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

const success = arrayStride % 4 === 0;
const success = { shader: true, pipeline: arrayStride % 4 === 0 };
t.testVertexState(success, vertexBuffers);
});

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

const success = testShaderLocation < kMaxVertexAttributes;
const success = { shader: true, pipeline: testShaderLocation < kMaxVertexAttributes };
t.testVertexState(success, vertexBuffers);
});

Expand Down Expand Up @@ -360,18 +369,26 @@ g.test('vertex_attribute_shaderLocation_unique')

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

g.test('vertex_shader_input_location_limit')
.desc(
`Test that vertex shader's input's location decoration must be less than maxVertexAttributes.
- Test for shaderLocation 0, 1, limit - 1, limit`
- Test for shaderLocation 0, 1, limit - 1, limit, -1, 0x7fffffff, 2 ** 32`
)
.paramsSubcasesOnly(u =>
u //
.combine('testLocation', [0, 1, kMaxVertexAttributes - 1, kMaxVertexAttributes, -1, 2 ** 32])
.combine('testLocation', [
0,
1,
kMaxVertexAttributes - 1,
kMaxVertexAttributes,
-1,
0x7fffffff,
2 ** 32,
])
)
.fn(t => {
const { testLocation } = t.params;
Expand All @@ -396,7 +413,13 @@ g.test('vertex_shader_input_location_limit')
},
];

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

Expand Down Expand Up @@ -438,14 +461,15 @@ g.test('vertex_shader_input_location_in_vertex_state')
extraAttributeCount,
extraAttributeSkippedLocations: [testShaderLocation],
});
t.testVertexState(false, vertexBuffers, shader);

t.testVertexState({ shader: true, pipeline: false }, vertexBuffers, shader);

// Add an attribute for the test location and try again.
addTestAttributes(attributes, {
testAttribute: { format: 'float32', shaderLocation: testShaderLocation, offset: 0 },
testAttributeAtStart,
});
t.testVertexState(true, vertexBuffers, shader);
t.testVertexState({ shader: true, pipeline: true }, vertexBuffers, shader);
});

g.test('vertex_shader_type_matches_attribute_format')
Expand Down Expand Up @@ -484,7 +508,7 @@ g.test('vertex_shader_type_matches_attribute_format')
float: 'f32',
}[kVertexFormatInfo[format].type];

const success = requiredBaseType === shaderBaseType;
const success = { shader: true, pipeline: requiredBaseType === shaderBaseType };
t.testVertexState(
success,
[
Expand Down Expand Up @@ -554,7 +578,7 @@ g.test('vertex_attribute_offset_alignment')

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

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

const success = offset + formatSize <= limit;
const success = { shader: true, pipeline: offset + formatSize <= limit };
t.testVertexState(success, vertexBuffers);
});

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

t.testVertexState(true, [{ arrayStride: 0, attributes }]);
t.testVertexState({ shader: true, pipeline: true }, [{ arrayStride: 0, attributes }]);
});

0 comments on commit cd2eac6

Please sign in to comment.