Test that vertex attributes can overlap
Bug: dawn:433
Change-Id: I47d9ffe16d6ad7730628dc27ec6708006cf4384d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/22560
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
diff --git a/src/tests/end2end/VertexStateTests.cpp b/src/tests/end2end/VertexStateTests.cpp
index 404cdf2..e65fefa 100644
--- a/src/tests/end2end/VertexStateTests.cpp
+++ b/src/tests/end2end/VertexStateTests.cpp
@@ -15,6 +15,7 @@
#include "tests/DawnTest.h"
#include "common/Assert.h"
+#include "common/Math.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/WGPUHelpers.h"
@@ -521,6 +522,83 @@
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{kMaxVertexBuffers - 1, &buffer0}});
}
+// Test that overlapping vertex attributes are permitted and load data correctly
+TEST_P(VertexStateTest, OverlappingVertexAttributes) {
+ utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 3, 3);
+
+ utils::ComboVertexStateDescriptor vertexState =
+ MakeVertexState({{16,
+ InputStepMode::Vertex,
+ {
+ // "****" represents the bytes we'll actually read in the shader.
+ {0, 0 /* offset */, VertexFormat::Float4}, // |****|----|----|----|
+ {1, 4 /* offset */, VertexFormat::UInt2}, // |****|****|
+ {2, 8 /* offset */, VertexFormat::Half4}, // |-----****|
+ {3, 0 /* offset */, VertexFormat::Float}, // |****|
+ }}});
+
+ struct Data {
+ float fvalue;
+ uint32_t uints[2];
+ uint16_t halfs[2];
+ };
+ static_assert(sizeof(Data) == 16, "");
+ Data data {1.f, {2u, 3u}, {Float32ToFloat16(4.f), Float32ToFloat16(5.f)}};
+
+ wgpu::Buffer vertexBuffer =
+ utils::CreateBufferFromData(device, &data, sizeof(data), wgpu::BufferUsage::Vertex);
+
+ utils::ComboRenderPipelineDescriptor pipelineDesc(device);
+ pipelineDesc.vertexStage.module =
+ utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
+ #version 450
+ layout(location = 0) in vec4 attr0;
+ layout(location = 1) in uvec2 attr1;
+ layout(location = 2) in vec4 attr2;
+ layout(location = 3) in float attr3;
+
+ layout(location = 0) out vec4 color;
+
+ void main() {
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+ gl_PointSize = 1.0;
+
+ bool success = (
+ attr0.x == 1.0f &&
+ attr1.x == 2u &&
+ attr1.y == 3u &&
+ attr2.z == 4.0f &&
+ attr2.w == 5.0f &&
+ attr3 == 1.0f
+ );
+ color = success ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);
+ })");
+ pipelineDesc.cFragmentStage.module =
+ utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
+ #version 450
+ layout(location = 0) in vec4 color;
+ layout(location = 0) out vec4 fragColor;
+ void main() {
+ fragColor = color;
+ })");
+ pipelineDesc.vertexState = &vertexState;
+ pipelineDesc.cColorStates[0].format = renderPass.colorFormat;
+ pipelineDesc.primitiveTopology = wgpu::PrimitiveTopology::PointList;
+
+ wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDesc);
+
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+ wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
+ pass.SetPipeline(pipeline);
+ pass.SetVertexBuffer(0, vertexBuffer);
+ pass.Draw(1);
+ pass.EndPass();
+ wgpu::CommandBuffer commands = encoder.Finish();
+ queue.Submit(1, &commands);
+
+ EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 1, 1);
+}
+
DAWN_INSTANTIATE_TEST(VertexStateTest, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());
// TODO for the input state: