// Copyright 2021 The Dawn Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "tests/unittests/validation/ValidationTest.h" #include "utils/ComboRenderPipelineDescriptor.h" #include "utils/WGPUHelpers.h" namespace { class WriteBufferTest : public ValidationTest { public: wgpu::Buffer CreateWritableBuffer(uint64_t size) { wgpu::BufferDescriptor desc; desc.usage = wgpu::BufferUsage::CopyDst; desc.size = size; return device.CreateBuffer(&desc); } wgpu::CommandBuffer EncodeWriteBuffer(wgpu::Buffer buffer, uint64_t bufferOffset, uint64_t size) { std::vector data(size); wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); encoder.WriteBuffer(buffer, bufferOffset, data.data(), size); return encoder.Finish(); } }; // Tests that the buffer offset is validated to be a multiple of 4 bytes. TEST_F(WriteBufferTest, OffsetAlignment) { wgpu::Buffer buffer = CreateWritableBuffer(64); EncodeWriteBuffer(buffer, 0, 4); EncodeWriteBuffer(buffer, 4, 4); EncodeWriteBuffer(buffer, 60, 4); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 1, 4)); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 2, 4)); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 3, 4)); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 5, 4)); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 11, 4)); } // Tests that the buffer size is validated to be a multiple of 4 bytes. TEST_F(WriteBufferTest, SizeAlignment) { wgpu::Buffer buffer = CreateWritableBuffer(64); EncodeWriteBuffer(buffer, 0, 64); EncodeWriteBuffer(buffer, 4, 60); EncodeWriteBuffer(buffer, 40, 24); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 0, 63)); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 4, 1)); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 4, 2)); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 40, 23)); } // Tests that the buffer size and offset are validated to fit within the bounds of the buffer. TEST_F(WriteBufferTest, BufferBounds) { wgpu::Buffer buffer = CreateWritableBuffer(64); EncodeWriteBuffer(buffer, 0, 64); EncodeWriteBuffer(buffer, 4, 60); EncodeWriteBuffer(buffer, 40, 24); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 0, 68)); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 4, 64)); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 60, 8)); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 64, 4)); } // Tests that the destination buffer's usage is validated to contain CopyDst. TEST_F(WriteBufferTest, RequireCopyDstUsage) { wgpu::BufferDescriptor desc; desc.usage = wgpu::BufferUsage::CopySrc; desc.size = 64; wgpu::Buffer buffer = device.CreateBuffer(&desc); ASSERT_DEVICE_ERROR(EncodeWriteBuffer(buffer, 0, 64)); } // Tests that the destination buffer's state is validated at submission. TEST_F(WriteBufferTest, ValidBufferState) { wgpu::BufferDescriptor desc; desc.usage = wgpu::BufferUsage::CopyDst; desc.size = 64; desc.mappedAtCreation = true; wgpu::Buffer buffer = device.CreateBuffer(&desc); wgpu::CommandBuffer commands = EncodeWriteBuffer(buffer, 0, 64); ASSERT_DEVICE_ERROR(device.GetQueue().Submit(1, &commands)); commands = EncodeWriteBuffer(buffer, 0, 64); buffer.Unmap(); device.GetQueue().Submit(1, &commands); } } // namespace