From 3835edde108d07c90da568eb673779976071b90d Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Tue, 18 Jul 2017 13:18:58 -0400 Subject: [PATCH] Add validation for buffer offset --- src/backend/CommandBuffer.cpp | 12 ++++ .../CopyCommandsValidationTests.cpp | 63 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/backend/CommandBuffer.cpp b/src/backend/CommandBuffer.cpp index 29617b76e8..4d3c02f736 100644 --- a/src/backend/CommandBuffer.cpp +++ b/src/backend/CommandBuffer.cpp @@ -70,6 +70,16 @@ namespace backend { return true; } + bool ValidateTexelBufferOffset(CommandBufferBuilder* builder, TextureBase* texture, const BufferCopyLocation& location) { + uint32_t texelSize = static_cast(TextureFormatPixelSize(texture->GetFormat())); + if (location.offset % texelSize != 0) { + builder->HandleError("Buffer offset must be a multiple of the texel size"); + return false; + } + + return true; + } + bool ComputeTextureCopyBufferSize(CommandBufferBuilder*, const TextureCopyLocation& location, uint32_t rowPitch, uint32_t* bufferSize) { // TODO(cwallez@chromium.org): check for overflows *bufferSize = (rowPitch * (location.height - 1) + location.width) * location.depth; @@ -437,6 +447,7 @@ namespace backend { !ComputeTextureCopyBufferSize(this, copy->destination, copy->rowPitch, &bufferCopySize) || !ValidateCopyLocationFitsInTexture(this, copy->destination) || !ValidateCopySizeFitsInBuffer(this, copy->source, bufferCopySize) || + !ValidateTexelBufferOffset(this, copy->destination.texture.Get(), copy->source) || !state->ValidateCanCopy() || !state->ValidateCanUseBufferAs(copy->source.buffer.Get(), nxt::BufferUsageBit::TransferSrc) || !state->ValidateCanUseTextureAs(copy->destination.texture.Get(), nxt::TextureUsageBit::TransferDst)) { @@ -454,6 +465,7 @@ namespace backend { !ComputeTextureCopyBufferSize(this, copy->source, copy->rowPitch, &bufferCopySize) || !ValidateCopyLocationFitsInTexture(this, copy->source) || !ValidateCopySizeFitsInBuffer(this, copy->destination, bufferCopySize) || + !ValidateTexelBufferOffset(this, copy->source.texture.Get(), copy->destination) || !state->ValidateCanCopy() || !state->ValidateCanUseTextureAs(copy->source.texture.Get(), nxt::TextureUsageBit::TransferSrc) || !state->ValidateCanUseBufferAs(copy->destination.buffer.Get(), nxt::BufferUsageBit::TransferDst)) { diff --git a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp index 91893ac728..efbff708bd 100644 --- a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp +++ b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp @@ -314,6 +314,37 @@ TEST_F(CopyCommandTest_B2T, IncorrectRowPitch) { } } +// Test B2T copies with incorrect buffer offset usage +TEST_F(CopyCommandTest_B2T, IncorrectBufferOffset) { + uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1); + nxt::Buffer source = CreateFrozenBuffer(bufferSize, nxt::BufferUsageBit::TransferSrc); + nxt::Texture destination = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm, + nxt::TextureUsageBit::TransferDst); + + // Correct usage + { + nxt::CommandBuffer commands = AssertWillBeSuccess(device.CreateCommandBufferBuilder()) + .CopyBufferToTexture(source, bufferSize - 4, 256, destination, 0, 0, 0, 1, 1, 1, 0) + .GetResult(); + } + // Incorrect usages + { + nxt::CommandBuffer commands = AssertWillBeError(device.CreateCommandBufferBuilder()) + .CopyBufferToTexture(source, bufferSize - 5, 256, destination, 0, 0, 0, 1, 1, 1, 0) + .GetResult(); + } + { + nxt::CommandBuffer commands = AssertWillBeError(device.CreateCommandBufferBuilder()) + .CopyBufferToTexture(source, bufferSize - 6, 256, destination, 0, 0, 0, 1, 1, 1, 0) + .GetResult(); + } + { + nxt::CommandBuffer commands = AssertWillBeError(device.CreateCommandBufferBuilder()) + .CopyBufferToTexture(source, bufferSize - 7, 256, destination, 0, 0, 0, 1, 1, 1, 0) + .GetResult(); + } +} + class CopyCommandTest_T2B : public CopyCommandTest { }; @@ -513,3 +544,35 @@ TEST_F(CopyCommandTest_T2B, IncorrectRowPitch) { .GetResult(); } } + +// Test T2B copies with incorrect buffer offset usage +TEST_F(CopyCommandTest_T2B, IncorrectBufferOffset) { + uint32_t bufferSize = BufferSizeForTextureCopy(128, 16, 1); + nxt::Texture source = CreateFrozen2DTexture(128, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm, + nxt::TextureUsageBit::TransferSrc); + nxt::Buffer destination = CreateFrozenBuffer(bufferSize, nxt::BufferUsageBit::TransferDst); + + // Correct usage + { + nxt::CommandBuffer commands = AssertWillBeSuccess(device.CreateCommandBufferBuilder()) + .CopyTextureToBuffer(source, 0, 0, 0, 1, 1, 1, 0, destination, bufferSize - 4, 256) + .GetResult(); + } + // Incorrect usages + { + nxt::CommandBuffer commands = AssertWillBeError(device.CreateCommandBufferBuilder()) + .CopyTextureToBuffer(source, 0, 0, 0, 1, 1, 1, 0, destination, bufferSize - 5, 256) + .GetResult(); + } + { + nxt::CommandBuffer commands = AssertWillBeError(device.CreateCommandBufferBuilder()) + .CopyTextureToBuffer(source, 0, 0, 0, 1, 1, 1, 0, destination, bufferSize - 6, 256) + .GetResult(); + } + { + nxt::CommandBuffer commands = AssertWillBeError(device.CreateCommandBufferBuilder()) + .CopyTextureToBuffer(source, 0, 0, 0, 1, 1, 1, 0, destination, bufferSize - 7, 256) + .GetResult(); + } +} +