diff --git a/src/tests/unittests/validation/VertexStateValidationTests.cpp b/src/tests/unittests/validation/VertexStateValidationTests.cpp index 42d7025e90..0f114ab1d2 100644 --- a/src/tests/unittests/validation/VertexStateValidationTests.cpp +++ b/src/tests/unittests/validation/VertexStateValidationTests.cpp @@ -21,17 +21,14 @@ class VertexStateTest : public ValidationTest { protected: void CreatePipeline(bool success, const utils::ComboVertexStateDescriptor& state, - std::string vertexSource) { - wgpu::ShaderModule vsModule = utils::CreateShaderModule( - device, utils::SingleShaderStage::Vertex, vertexSource.c_str()); - wgpu::ShaderModule fsModule = - utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( - #version 450 - layout(location = 0) out vec4 fragColor; - void main() { - fragColor = vec4(1.0, 0.0, 0.0, 1.0); - } - )"); + const char* vertexSource) { + wgpu::ShaderModule vsModule = utils::CreateShaderModuleFromWGSL(device, vertexSource); + wgpu::ShaderModule fsModule = utils::CreateShaderModuleFromWGSL(device, R"( + [[location(0)]] var fragColor : vec4; + [[stage(fragment)]] fn main() -> void { + fragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + )"); utils::ComboRenderPipelineDescriptor descriptor(device); descriptor.vertexStage.module = vsModule; @@ -45,17 +42,19 @@ class VertexStateTest : public ValidationTest { device.CreateRenderPipeline(&descriptor); } } + + const char* kDummyVertexShader = R"( + [[builtin(position)]] var Position : vec4; + [[stage(vertex)]] fn main() -> void { + Position = vec4(0.0, 0.0, 0.0, 0.0); + } + )"; }; // Check an empty vertex input is valid TEST_F(VertexStateTest, EmptyIsOk) { utils::ComboVertexStateDescriptor state; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); } // Check null buffer is valid @@ -66,12 +65,7 @@ TEST_F(VertexStateTest, NullBufferIsOk) { state.cVertexBuffers[0].arrayStride = 0; state.cVertexBuffers[0].attributeCount = 0; state.cVertexBuffers[0].attributes = nullptr; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // One null buffer (buffer[0]) followed by a buffer (buffer[1]) is OK state.vertexBufferCount = 2; @@ -79,12 +73,7 @@ TEST_F(VertexStateTest, NullBufferIsOk) { state.cVertexBuffers[1].attributeCount = 1; state.cVertexBuffers[1].attributes = &state.cAttributes[0]; state.cAttributes[0].shaderLocation = 0; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Null buffer (buffer[2]) sitting between buffers (buffer[1] and buffer[3]) is OK state.vertexBufferCount = 4; @@ -93,12 +82,7 @@ TEST_F(VertexStateTest, NullBufferIsOk) { state.cVertexBuffers[3].attributeCount = 1; state.cVertexBuffers[3].attributes = &state.cAttributes[1]; state.cAttributes[1].shaderLocation = 1; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); } // Check validation that pipeline vertex buffers are backed by attributes in the vertex input @@ -114,29 +98,29 @@ TEST_F(VertexStateTest, PipelineCompatibility) { // Control case: pipeline with one input per attribute CreatePipeline(true, state, R"( - #version 450 - layout(location = 0) in vec4 a; - layout(location = 1) in vec4 b; - void main() { - gl_Position = vec4(0.0); + [[location(0)]] var a : vec4; + [[location(1)]] var b : vec4; + [[builtin(position)]] var Position : vec4; + [[stage(vertex)]] fn main() -> void { + Position = vec4(0.0, 0.0, 0.0, 0.0); } )"); // Check it is valid for the pipeline to use a subset of the VertexState CreatePipeline(true, state, R"( - #version 450 - layout(location = 0) in vec4 a; - void main() { - gl_Position = vec4(0.0); + [[location(0)]] var a : vec4; + [[builtin(position)]] var Position : vec4; + [[stage(vertex)]] fn main() -> void { + Position = vec4(0.0, 0.0, 0.0, 0.0); } )"); // Check for an error when the pipeline uses an attribute not in the vertex input CreatePipeline(false, state, R"( - #version 450 - layout(location = 2) in vec4 a; - void main() { - gl_Position = vec4(0.0); + [[location(2)]] var a : vec4; + [[builtin(position)]] var Position : vec4; + [[stage(vertex)]] fn main() -> void { + Position = vec4(0.0, 0.0, 0.0, 0.0); } )"); } @@ -148,21 +132,11 @@ TEST_F(VertexStateTest, StrideZero) { state.vertexBufferCount = 1; state.cVertexBuffers[0].arrayStride = 0; state.cVertexBuffers[0].attributeCount = 1; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Works ok with attributes at a large-ish offset state.cAttributes[0].offset = 128; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); } // Check validation that vertex attribute offset should be within vertex buffer arrayStride, @@ -176,30 +150,15 @@ TEST_F(VertexStateTest, SetOffsetOutOfBounds) { state.cAttributes[0].shaderLocation = 0; state.cAttributes[1].shaderLocation = 1; state.cAttributes[1].offset = sizeof(float); - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Test vertex attribute offset exceed vertex buffer arrayStride range state.cVertexBuffers[0].arrayStride = sizeof(float); - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); // It's OK if arrayStride is zero state.cVertexBuffers[0].arrayStride = 0; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); } // Check out of bounds condition on total number of vertex buffers @@ -212,21 +171,11 @@ TEST_F(VertexStateTest, SetVertexBuffersNumLimit) { state.cVertexBuffers[i].attributes = &state.cAttributes[i]; state.cAttributes[i].shaderLocation = i; } - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Test vertex buffer number exceed the limit state.vertexBufferCount = kMaxVertexBuffers + 1; - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); } // Check out of bounds condition on total number of vertex attributes @@ -238,22 +187,12 @@ TEST_F(VertexStateTest, SetVertexAttributesNumLimit) { for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) { state.cAttributes[i].shaderLocation = i; } - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Test vertex attribute number exceed the limit state.cVertexBuffers[1].attributeCount = 1; state.cVertexBuffers[1].attributes = &state.cAttributes[kMaxVertexAttributes - 1]; - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); } // Check out of bounds condition on input arrayStride @@ -263,21 +202,11 @@ TEST_F(VertexStateTest, SetInputStrideOutOfBounds) { state.vertexBufferCount = 1; state.cVertexBuffers[0].arrayStride = kMaxVertexBufferStride; state.cVertexBuffers[0].attributeCount = 1; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Test input arrayStride OOB state.cVertexBuffers[0].arrayStride = kMaxVertexBufferStride + 1; - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); } // Check multiple of 4 bytes constraint on input arrayStride @@ -287,21 +216,11 @@ TEST_F(VertexStateTest, SetInputStrideNotAligned) { state.vertexBufferCount = 1; state.cVertexBuffers[0].arrayStride = 4; state.cVertexBuffers[0].attributeCount = 1; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Test input arrayStride not multiple of 4 bytes state.cVertexBuffers[0].arrayStride = 2; - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); } // Test that we cannot set an already set attribute @@ -311,23 +230,13 @@ TEST_F(VertexStateTest, AlreadySetAttribute) { state.vertexBufferCount = 1; state.cVertexBuffers[0].attributeCount = 1; state.cAttributes[0].shaderLocation = 0; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Oh no, attribute 0 is set twice state.cVertexBuffers[0].attributeCount = 2; state.cAttributes[0].shaderLocation = 0; state.cAttributes[1].shaderLocation = 0; - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); } // Test that a arrayStride of 0 is valid @@ -339,21 +248,11 @@ TEST_F(VertexStateTest, SetSameShaderLocation) { state.cAttributes[0].shaderLocation = 0; state.cAttributes[1].shaderLocation = 1; state.cAttributes[1].offset = sizeof(float); - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Test same shader location in two attributes in the same buffer state.cAttributes[1].shaderLocation = 0; - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); // Test same shader location in two attributes in different buffers state.vertexBufferCount = 2; @@ -362,12 +261,7 @@ TEST_F(VertexStateTest, SetSameShaderLocation) { state.cVertexBuffers[1].attributeCount = 1; state.cVertexBuffers[1].attributes = &state.cAttributes[1]; state.cAttributes[1].shaderLocation = 0; - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); } // Check out of bounds condition on attribute shader location @@ -377,21 +271,11 @@ TEST_F(VertexStateTest, SetAttributeLocationOutOfBounds) { state.vertexBufferCount = 1; state.cVertexBuffers[0].attributeCount = 1; state.cAttributes[0].shaderLocation = kMaxVertexAttributes - 1; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Test attribute location OOB state.cAttributes[0].shaderLocation = kMaxVertexAttributes; - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); } // Check attribute offset out of bounds @@ -401,21 +285,11 @@ TEST_F(VertexStateTest, SetAttributeOffsetOutOfBounds) { state.vertexBufferCount = 1; state.cVertexBuffers[0].attributeCount = 1; state.cAttributes[0].offset = kMaxVertexAttributeEnd - sizeof(wgpu::VertexFormat::Float); - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Test attribute offset out of bounds state.cAttributes[0].offset = kMaxVertexAttributeEnd - 1; - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); } // Check multiple of 4 bytes constraint on offset @@ -425,21 +299,11 @@ TEST_F(VertexStateTest, SetOffsetNotAligned) { state.vertexBufferCount = 1; state.cVertexBuffers[0].attributeCount = 1; state.cAttributes[0].offset = 4; - CreatePipeline(true, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(true, state, kDummyVertexShader); // Test offset not multiple of 4 bytes state.cAttributes[0].offset = 2; - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); } // Check attribute offset overflow @@ -448,12 +312,7 @@ TEST_F(VertexStateTest, SetAttributeOffsetOverflow) { state.vertexBufferCount = 1; state.cVertexBuffers[0].attributeCount = 1; state.cAttributes[0].offset = std::numeric_limits::max(); - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); } // Check for some potential underflow in the vertex input validation @@ -463,10 +322,5 @@ TEST_F(VertexStateTest, VertexFormatLargerThanNonZeroStride) { state.cVertexBuffers[0].arrayStride = 4; state.cVertexBuffers[0].attributeCount = 1; state.cAttributes[0].format = wgpu::VertexFormat::Float4; - CreatePipeline(false, state, R"( - #version 450 - void main() { - gl_Position = vec4(0.0); - } - )"); + CreatePipeline(false, state, kDummyVertexShader); }