D3D12: Fix order of Tint transforms

FirstIndexOffset must happen after BindingRemapper otherwise some
invalid AST is produced after FirstIndexOffset.

This was found running a CTS test on Windows:
validation,vertex_state:vertex_shader_type_matches_attribute_format

Also adds a regression test.

Bug: dawn:1014

Change-Id: Icbe4b3adb5e5844ffc8435e0e67056c7dff23970
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/59281
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2021-07-23 15:49:47 +00:00 committed by Dawn LUCI CQ
parent 9bb32ba330
commit 21528281fd
2 changed files with 51 additions and 1 deletions

View File

@ -251,13 +251,19 @@ namespace dawn_native { namespace d3d12 {
if (GetDevice()->IsRobustnessEnabled()) {
transformManager.Add<tint::transform::BoundArrayAccessors>();
}
transformManager.Add<tint::transform::BindingRemapper>();
// The FirstIndexOffset transform must be done after the BindingRemapper because it assumes
// that the register space has already flattened (and uses the next register). Otherwise
// intermediate ASTs can be produced where the extra registers conflict with one of the
// user-declared bind points.
if (stage == SingleShaderStage::Vertex) {
transformManager.Add<tint::transform::FirstIndexOffset>();
transformInputs.Add<tint::transform::FirstIndexOffset::BindingPoint>(
layout->GetFirstIndexOffsetShaderRegister(),
layout->GetFirstIndexOffsetRegisterSpace());
}
transformManager.Add<tint::transform::BindingRemapper>();
transformManager.Add<tint::transform::Renamer>();
if (GetDevice()->IsToggleEnabled(Toggle::DisableSymbolRenaming)) {

View File

@ -322,6 +322,50 @@ fn ep_func() {
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, shader.c_str()));
}
// This is a regression test for an issue caused by the FirstIndexOffset transfrom being done before
// the BindingRemapper, causing an intermediate AST to be invalid (and fail the overall
// compilation).
TEST_P(ShaderTests, FirstIndexOffsetRegisterConflictInHLSLTransforms) {
// TODO(crbug.com/dawn/658): Crashes on bots because there are two entrypoints in the shader.
DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
const char* shader = R"(
// Dumped WGSL:
struct Inputs {
[[location(1)]] attrib1 : u32;
// The extra register added to handle base_vertex for vertex_index conflicts with [1]
[[builtin(vertex_index)]] vertexIndex: u32;
};
// [1] a binding point that conflicts with the regitster
[[block]] struct S1 { data : array<vec4<u32>, 20>; };
[[group(0), binding(1)]] var<uniform> providedData1 : S1;
[[stage(vertex)]] fn vsMain(input : Inputs) -> [[builtin(position)]] vec4<f32> {
ignore(providedData1.data[input.vertexIndex][0]);
return vec4<f32>();
}
[[stage(fragment)]] fn fsMain() -> [[location(0)]] vec4<f32> {
return vec4<f32>();
}
)";
auto module = utils::CreateShaderModule(device, shader);
utils::ComboRenderPipelineDescriptor rpDesc;
rpDesc.vertex.module = module;
rpDesc.vertex.entryPoint = "vsMain";
rpDesc.cFragment.module = module;
rpDesc.cFragment.entryPoint = "fsMain";
rpDesc.vertex.bufferCount = 1;
rpDesc.cBuffers[0].attributeCount = 1;
rpDesc.cBuffers[0].arrayStride = 16;
rpDesc.cAttributes[0].shaderLocation = 1;
rpDesc.cAttributes[0].format = wgpu::VertexFormat::Uint8x2;
device.CreateRenderPipeline(&rpDesc);
}
DAWN_INSTANTIATE_TEST(ShaderTests,
D3D12Backend(),
MetalBackend(),