Skip to content

Commit

Permalink
Add shader validation tests on the usage of @blend_src (#3839)
Browse files Browse the repository at this point in the history
* Add shader validation tests on the usage of `@blend_src`

This patch adds shader validation tests on the usage of `@blend_src`.
According to the latest WGSL SPEC,
- `@blend_src` can only be used on a struct member with `@location`
  attribute
- If `@blend_src` is declared on a member of a struct, the struct
  must exactly have two members with `@location` attribute: one has
  `@location(0) @blend_src(0)` and another has `@location(0) @blend_src(1)`.

* Add more tests on different variable declarations

* Address reviewer's comments
  • Loading branch information
Jiawei-Shao authored Jul 5, 2024
1 parent 9504c75 commit e80efbc
Showing 1 changed file with 243 additions and 0 deletions.
243 changes: 243 additions & 0 deletions src/webgpu/shader/validation/extension/dual_source_blending.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,246 @@ ${kStageIOValidationTests[t.params.attr].shader}
`;
t.expectCompileResult(kStageIOValidationTests[t.params.attr].pass, code);
});

const kUsageValidationTests = {
const: {
code: `@blend_src(0) const color = 1.2;`,
pass: false,
use_default_main_function: true,
},
override: {
code: `@blend_src(0) @id(0) override color : f32;`,
pass: false,
use_default_main_function: true,
},
let: {
code: `
@fragment fn main() -> vec4f {
let @blend_src(0) color = vec4f();
return color;
}
`,
pass: false,
use_default_main_function: false,
},
var_private: {
code: `@blend_src(0) var<private> color : vec4f;`,
pass: false,
use_default_main_function: true,
},
var_function: {
code: `
@fragment fn main() -> vec4f {
var @blend_src(0) color : vec4f;
color = vec4f();
return color;
}
`,
pass: false,
use_default_main_function: false,
},
function_declaration: {
code: `
@blend_src(0) fn fun() {}
`,
pass: false,
use_default_main_function: true,
},
non_entrypoint_function_input_non_struct: {
code: `
fn fun(@blend_src(0) color : vec4f) -> vec4f {
return color;
}
`,
pass: false,
use_default_main_function: true,
},
non_entrypoint_function_output_non_struct: {
code: `
fn fun() -> @blend_src(0) vec4f {
return vec4f();
}
`,
pass: false,
use_default_main_function: true,
},
entrypoint_input_non_struct: {
code: `
@fragment fn main(@location(0) @blend_src(0) color : vec4f) -> @location(0) vec4f {
return color;
}
`,
pass: false,
use_default_main_function: false,
},
entrypoint_output_non_struct: {
code: `
@fragment fn main() -> @location(0) @blend_src(0) vec4f {
return vec4f();
}
`,
pass: false,
use_default_main_function: false,
},
struct_member_only_blend_src_0: {
code: `
struct BlendSrcStruct {
@location(0) @blend_src(0) color : vec4f,
}
`,
pass: false,
use_default_main_function: true,
},
struct_member_only_blend_src_1: {
code: `
struct BlendSrcStruct {
@location(0) @blend_src(1) blend : vec4f,
}
`,
pass: false,
use_default_main_function: true,
},
struct_member_no_location_blend_src_0: {
code: `
struct BlendSrcStruct {
@blend_src(0) color : vec4f,
@location(0) @blend_src(1) blend : vec4f,
}
`,
pass: false,
use_default_main_function: true,
},
struct_member_no_location_blend_src_1: {
code: `
struct BlendSrcStruct {
@location(0) @blend_src(0) color : vec4f,
@blend_src(1) blend : vec4f,
}
`,
pass: false,
use_default_main_function: true,
},
struct_member_duplicate_blend_src_0: {
code: `
struct BlendSrcStruct {
@location(0) @blend_src(0) color : vec4f,
@location(0) @blend_src(0) blend : vec4f,
}
`,
pass: false,
use_default_main_function: true,
},
struct_member_duplicate_blend_src_1: {
code: `
struct BlendSrcStruct {
@location(0) @blend_src(1) color : vec4f,
@location(0) @blend_src(1) blend : vec4f,
}
`,
pass: false,
use_default_main_function: true,
},
struct_member_has_non_zero_location_blend_src_0: {
code: `
struct BlendSrcStruct {
@location(0) @blend_src(0) color1 : vec4f,
@location(1) @blend_src(0) color2 : vec4f,
@location(0) @blend_src(1) blend : vec4f,
}
`,
pass: false,
use_default_main_function: true,
},
struct_member_has_non_zero_location_blend_src_1: {
code: `
struct BlendSrcStruct {
@location(0) @blend_src(0) color : vec4f,
@location(0) @blend_src(1) blend1 : vec4f,
@location(1) @blend_src(1) blend2 : vec4f,
}
`,
pass: false,
use_default_main_function: true,
},
struct_member_non_zero_location_blend_src_0_blend_src_1: {
code: `
struct BlendSrcStruct {
@location(1) @blend_src(0) color : vec4f,
@location(1) @blend_src(1) blend : vec4f,
}
`,
pass: false,
use_default_main_function: true,
},
struct_member_has_non_zero_location_no_blend_src: {
code: `
struct BlendSrcStruct {
@location(0) @blend_src(0) color : vec4f,
@location(0) @blend_src(1) blend : vec4f,
@location(1) color2 : vec4f,
}
`,
pass: false,
use_default_main_function: true,
},
struct_member_no_location_no_blend_src: {
code: `
struct BlendSrcStruct {
@location(0) @blend_src(0) color : vec4f,
@location(0) @blend_src(1) blend : vec4f,
depth : f32,
}
`,
pass: true,
use_default_main_function: true,
},
struct_member_blend_src_and_builtin: {
code: `
struct BlendSrcStruct {
@location(0) @blend_src(0) color : vec4f,
@location(0) @blend_src(1) blend : vec4f,
@builtin(frag_depth) depth : f32,
}
`,
pass: true,
use_default_main_function: true,
},
struct_member_location_0_blend_src_0_blend_src_1: {
code: `
struct BlendSrcStruct {
@location(0) @blend_src(0) color : vec4f,
@location(0) @blend_src(1) blend : vec4f,
}
`,
pass: true,
use_default_main_function: true,
},
};

g.test('blend_src_usage')
.desc(
`Test that blend_src can only be used on a member of a structure, and must be used together with
the location attribute. In addition, if blend_src is used on a member of a structure, there must
be exactly 2 members that have location attribute in the structure: one is @location(0)
@blend_src(0) and another is @location(0) @blend_src(1).`
)
.params(u => u.combine('attr', keysOf(kUsageValidationTests)))
.beforeAllSubcases(t =>
t.selectDeviceOrSkipTestCase({ requiredFeatures: ['dual-source-blending'] })
)
.fn(t => {
const code = `
enable dual_source_blending;
${kUsageValidationTests[t.params.attr].code}
${
kUsageValidationTests[t.params.attr].use_default_main_function
? `@fragment fn main() -> @location(0) vec4f {
return vec4f();
}`
: ''
}
`;
t.expectCompileResult(kUsageValidationTests[t.params.attr].pass, code);
});

0 comments on commit e80efbc

Please sign in to comment.