diff --git a/src/dawn_native/RenderEncoderBase.cpp b/src/dawn_native/RenderEncoderBase.cpp index f1e7c423be..2081a91da8 100644 --- a/src/dawn_native/RenderEncoderBase.cpp +++ b/src/dawn_native/RenderEncoderBase.cpp @@ -217,6 +217,11 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("Index format must be specified"); } + if (offset % uint64_t(IndexFormatSize(format)) != 0) { + return DAWN_VALIDATION_ERROR( + "Offset must be a multiple of the index format size"); + } + uint64_t bufferSize = buffer->GetSize(); if (offset > bufferSize) { return DAWN_VALIDATION_ERROR("Offset larger than the buffer size"); @@ -264,6 +269,10 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("Vertex buffer slot out of bounds"); } + if (offset % 4 != 0) { + return DAWN_VALIDATION_ERROR("Offset must be a multiple of 4"); + } + uint64_t bufferSize = buffer->GetSize(); if (offset > bufferSize) { return DAWN_VALIDATION_ERROR("Offset larger than the buffer size"); diff --git a/src/tests/unittests/validation/IndexBufferValidationTests.cpp b/src/tests/unittests/validation/IndexBufferValidationTests.cpp index 27f7b211ff..f2da91d57c 100644 --- a/src/tests/unittests/validation/IndexBufferValidationTests.cpp +++ b/src/tests/unittests/validation/IndexBufferValidationTests.cpp @@ -224,3 +224,39 @@ TEST_F(IndexBufferValidationTest, InvalidUsage) { ASSERT_DEVICE_ERROR(encoder.Finish()); } } + +// Check the alignment constraint on the index buffer offset. +TEST_F(IndexBufferValidationTest, OffsetAlignment) { + wgpu::Buffer indexBuffer = + utils::CreateBufferFromData(device, wgpu::BufferUsage::Index, {0, 1, 2}); + + DummyRenderPass renderPass(device); + // Control cases: index buffer offset is a multiple of the index format size + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); + pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint32, 0); + pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint32, 4); + pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint16, 0); + pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint16, 2); + pass.EndPass(); + encoder.Finish(); + } + + // Error case: index buffer offset isn't a multiple of 4 for IndexFormat::Uint32 + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); + pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint32, 2); + pass.EndPass(); + ASSERT_DEVICE_ERROR(encoder.Finish()); + } + // Error case: index buffer offset isn't a multiple of 2 for IndexFormat::Uint16 + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); + pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint16, 1); + pass.EndPass(); + ASSERT_DEVICE_ERROR(encoder.Finish()); + } +} diff --git a/src/tests/unittests/validation/VertexBufferValidationTests.cpp b/src/tests/unittests/validation/VertexBufferValidationTests.cpp index bcc88256cd..31a6f658ee 100644 --- a/src/tests/unittests/validation/VertexBufferValidationTests.cpp +++ b/src/tests/unittests/validation/VertexBufferValidationTests.cpp @@ -328,3 +328,29 @@ TEST_F(VertexBufferValidationTest, InvalidUsage) { ASSERT_DEVICE_ERROR(encoder.Finish()); } } + +// Check the alignment constraint on the index buffer offset. +TEST_F(VertexBufferValidationTest, OffsetAlignment) { + wgpu::Buffer vertexBuffer = MakeVertexBuffer(); + + DummyRenderPass renderPass(device); + // Control cases: vertex buffer offset is a multiple of 4 + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); + pass.SetVertexBuffer(0, vertexBuffer, 0); + pass.SetVertexBuffer(0, vertexBuffer, 4); + pass.SetVertexBuffer(0, vertexBuffer, 12); + pass.EndPass(); + encoder.Finish(); + } + + // Error case: vertex buffer offset isn't a multiple of 4 + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); + pass.SetVertexBuffer(0, vertexBuffer, 2); + pass.EndPass(); + ASSERT_DEVICE_ERROR(encoder.Finish()); + } +}