[Compat GL] Add render pipeline tests for TextureShaderBuiltinTests

For render pipeline cases, vertex and fragment shader could both have
textures in the same bind group needing builtins from uniform.

This triggers bug in the texture builtin uniforms transform.
First add a suppressed test.

Bug: 427409135
Change-Id: I8befffbfa3596b1586a75575c6c0365f60b1c0c7
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/248714
Commit-Queue: Shrek Shao <shrekshao@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/tests/end2end/TextureShaderBuiltinTests.cpp b/src/dawn/tests/end2end/TextureShaderBuiltinTests.cpp
index 8cf2f87..31564fb 100644
--- a/src/dawn/tests/end2end/TextureShaderBuiltinTests.cpp
+++ b/src/dawn/tests/end2end/TextureShaderBuiltinTests.cpp
@@ -789,6 +789,121 @@
     EXPECT_BUFFER_U32_RANGE_EQ(expected_2, buffer_2, 0, sizeof(expected_2) / sizeof(uint32_t));
 }
 
+// Regression Test for crbug.com/427409135, Test builtins are handled correctly for render pipeline,
+// when multiple entries in the same bind group from the vertex and fragment stage is not pushing to
+// the same offset in the uniform.
+TEST_P(TextureShaderBuiltinTests, RenderPipelineAvoidSameOffset) {
+    // TODO(crbug.com/427409135): remove this suppression once fixed.
+    DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
+
+    DAWN_TEST_UNSUPPORTED_IF(GetSupportedLimits().maxStorageBuffersInFragmentStage < 1);
+
+    // One texture builtin in the vertex shader
+    const char* vertexShader = R"(
+// Use sparse binding to test impact of binding remapping
+@group(0) @binding(1) var tex1 : texture_2d<f32>;
+
+struct VertexOutput {
+    @builtin(position) position: vec4<f32>,
+    @location(0) @interpolate(flat, either) value: u32,
+};
+
+@vertex fn main() -> VertexOutput {
+    var out : VertexOutput;
+    out.value = textureNumLevels(tex1);
+    // Make sure this position is not culled.
+    out.position = vec4f(0.5, 0.5, 0.5, 1.0);
+    return out;
+}
+    )";
+
+    // One texture builtin in the fragment shader, in the same bind group
+    const char* fragmentShader = R"(
+@group(1) @binding(0) var<storage, read_write> dstBuf : array<u32>;
+// Use sparse binding to test impact of binding remapping
+@group(0) @binding(3) var tex2 : texture_2d<f32>;
+
+struct VertexOutput {
+    @builtin(position) position: vec4<f32>,
+    @location(0) @interpolate(flat, either) value: u32,
+};
+
+@fragment fn main(in: VertexOutput) -> @location(0) vec4f{
+    dstBuf[0] = in.value;
+    dstBuf[1] = textureNumLevels(tex2);
+    return vec4f(1.0, 1.0, 1.0, 1.0);
+}
+    )";
+
+    constexpr uint32_t kMipLevels_1 = 2;
+    constexpr uint32_t kMipLevels_2 = 3;
+
+    wgpu::TextureDescriptor textureDesc = {};
+    textureDesc.size.width = 4;
+    textureDesc.size.height = 4;
+    textureDesc.format = kDefaultFormat;
+    textureDesc.mipLevelCount = kMipLevels_1;
+    textureDesc.usage = wgpu::TextureUsage::TextureBinding;
+    wgpu::TextureView texView_1 = device.CreateTexture(&textureDesc).CreateView();
+
+    textureDesc.mipLevelCount = kMipLevels_2;
+    wgpu::TextureView texView_2 = device.CreateTexture(&textureDesc).CreateView();
+
+    constexpr uint32_t expected[] = {
+        kMipLevels_1,
+        kMipLevels_2,
+    };
+
+    wgpu::BufferDescriptor bufferDesc;
+    bufferDesc.size = sizeof(expected);
+    bufferDesc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc;
+    wgpu::Buffer buffer = device.CreateBuffer(&bufferDesc);
+
+    wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
+        device, {
+                    {1, wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment,
+                     wgpu::TextureSampleType::Float, wgpu::TextureViewDimension::e2D},
+                    {3, wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment,
+                     wgpu::TextureSampleType::Float, wgpu::TextureViewDimension::e2D},
+                });
+    wgpu::BindGroupLayout bglBuffer = utils::MakeBindGroupLayout(
+        device, {
+                    {0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Storage},
+                });
+
+    wgpu::PipelineLayout pipelineLayout = utils::MakePipelineLayout(device, {bgl, bglBuffer});
+
+    utils::ComboRenderPipelineDescriptor pipelineDesc;
+    pipelineDesc.layout = pipelineLayout;
+    pipelineDesc.vertex.module = utils::CreateShaderModule(device, vertexShader);
+    pipelineDesc.cFragment.module = utils::CreateShaderModule(device, fragmentShader);
+    pipelineDesc.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
+    pipelineDesc.primitive.topology = wgpu::PrimitiveTopology::PointList;
+    wgpu::RenderPipeline renderPipeline = device.CreateRenderPipeline(&pipelineDesc);
+
+    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+    utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);
+    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
+
+    pass.SetPipeline(renderPipeline);
+    pass.SetBindGroup(0, utils::MakeBindGroup(device, bgl,
+                                              {
+                                                  {1, texView_1},
+                                                  {3, texView_2},
+                                              }));
+    pass.SetBindGroup(1, utils::MakeBindGroup(device, bglBuffer,
+                                              {
+                                                  {0, buffer},
+                                              }));
+    pass.Draw(1);
+    pass.End();
+
+    wgpu::CommandBuffer commands = encoder.Finish();
+    queue.Submit(1, &commands);
+
+    EXPECT_BUFFER_U32_RANGE_EQ(expected, buffer, 0, sizeof(expected) / sizeof(uint32_t));
+}
+
 DAWN_INSTANTIATE_TEST(TextureShaderBuiltinTests,
                       D3D11Backend(),
                       D3D12Backend(),