From 3e6db22fa82b9111958b3861980fe7cb21bb4322 Mon Sep 17 00:00:00 2001 From: Kai Ninomiya Date: Mon, 13 Jul 2020 17:23:33 +0000 Subject: [PATCH] Add BufferCopyView.layout and deprecate old fields Bug: dawn:22 Change-Id: Idc37faf5edaa01a6fb1a38d1a81022ad652cf428 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24622 Reviewed-by: Corentin Wallez Reviewed-by: Austin Eng Commit-Queue: Kai Ninomiya --- dawn.json | 1 + src/dawn_native/CommandEncoder.cpp | 72 +++++++---- src/dawn_native/CommandValidation.cpp | 7 +- src/dawn_native/CommandValidation.h | 2 +- .../end2end/D3D12ResourceWrappingTests.cpp | 13 +- src/tests/end2end/DeprecatedAPITests.cpp | 116 +++++++++++++++++- .../VulkanImageWrappingTestsDmaBuf.cpp | 41 ++----- .../VulkanImageWrappingTestsOpaqueFD.cpp | 28 +---- src/utils/WGPUHelpers.cpp | 8 +- 9 files changed, 192 insertions(+), 96 deletions(-) diff --git a/dawn.json b/dawn.json index 6a9cfd84f2..53431ee58e 100644 --- a/dawn.json +++ b/dawn.json @@ -217,6 +217,7 @@ "category": "structure", "extensible": true, "members": [ + {"name": "layout", "type": "texture data layout"}, {"name": "buffer", "type": "buffer"}, {"name": "offset", "type": "uint64_t", "default": 0}, {"name": "bytes per row", "type": "uint32_t"}, diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp index 01a5b62a4f..f228cb32df 100644 --- a/src/dawn_native/CommandEncoder.cpp +++ b/src/dawn_native/CommandEncoder.cpp @@ -406,6 +406,35 @@ namespace dawn_native { return fixedView; } + ResultOrError FixBufferCopyView(DeviceBase* device, + const BufferCopyView* view) { + BufferCopyView fixedView = *view; + + TextureDataLayout& layout = fixedView.layout; + if (layout.offset != 0 || layout.bytesPerRow != 0 || layout.rowsPerImage != 0) { + // Using non-deprecated path + if (fixedView.offset != 0 || fixedView.bytesPerRow != 0 || + fixedView.rowsPerImage != 0) { + return DAWN_VALIDATION_ERROR( + "WGPUBufferCopyView.offset/bytesPerRow/rowsPerImage is deprecated; use " + "only WGPUBufferCopyView.layout"); + } + } else if (fixedView.offset != 0 || fixedView.bytesPerRow != 0 || + fixedView.rowsPerImage != 0) { + device->EmitDeprecationWarning( + "WGPUBufferCopyView.offset/bytesPerRow/rowsPerImage is deprecated; use " + "WGPUBufferCopyView.layout"); + + layout.offset = fixedView.offset; + layout.bytesPerRow = fixedView.bytesPerRow; + layout.rowsPerImage = fixedView.rowsPerImage; + fixedView.offset = 0; + fixedView.bytesPerRow = 0; + fixedView.rowsPerImage = 0; + } + return fixedView; + } + } // namespace CommandEncoder::CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor*) @@ -570,12 +599,17 @@ namespace dawn_native { const TextureCopyView* destination, const Extent3D* copySize) { mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - // TODO(dawn:22): Remove once migration from GPUTextureCopyView.arrayLayer to + // TODO(crbug.com/dawn/22): Remove once migration from GPUTextureCopyView.arrayLayer to // GPUTextureCopyView.origin.z is done. TextureCopyView fixedDest; DAWN_TRY_ASSIGN(fixedDest, FixTextureCopyView(GetDevice(), destination)); destination = &fixedDest; + // TODO(crbug.com/dawn/22): Remove once migration to .layout is done. + BufferCopyView fixedSource; + DAWN_TRY_ASSIGN(fixedSource, FixBufferCopyView(GetDevice(), source)); + source = &fixedSource; + if (GetDevice()->IsValidationEnabled()) { DAWN_TRY(ValidateBufferCopyView(GetDevice(), *source)); DAWN_TRY(ValidateCanUseAs(source->buffer, wgpu::BufferUsage::CopySrc)); @@ -584,13 +618,7 @@ namespace dawn_native { DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst)); DAWN_TRY(ValidateTextureSampleCountInCopyCommands(destination->texture)); - TextureDataLayout sourceAsTextureDataLayout; - sourceAsTextureDataLayout.offset = source->offset; - sourceAsTextureDataLayout.bytesPerRow = source->bytesPerRow; - sourceAsTextureDataLayout.rowsPerImage = source->rowsPerImage; - - DAWN_TRY(ValidateLinearTextureData(sourceAsTextureDataLayout, - source->buffer->GetSize(), + DAWN_TRY(ValidateLinearTextureData(source->layout, source->buffer->GetSize(), destination->texture->GetFormat(), *copySize)); DAWN_TRY(ValidateTextureCopyRange(*destination, *copySize)); @@ -599,7 +627,7 @@ namespace dawn_native { } // Compute default value for rowsPerImage - uint32_t defaultedRowsPerImage = source->rowsPerImage; + uint32_t defaultedRowsPerImage = source->layout.rowsPerImage; if (defaultedRowsPerImage == 0) { defaultedRowsPerImage = copySize->height; } @@ -608,8 +636,8 @@ namespace dawn_native { CopyBufferToTextureCmd* copy = allocator->Allocate(Command::CopyBufferToTexture); copy->source.buffer = source->buffer; - copy->source.offset = source->offset; - copy->source.bytesPerRow = source->bytesPerRow; + copy->source.offset = source->layout.offset; + copy->source.bytesPerRow = source->layout.bytesPerRow; copy->source.rowsPerImage = defaultedRowsPerImage; copy->destination.texture = destination->texture; copy->destination.origin = destination->origin; @@ -624,12 +652,17 @@ namespace dawn_native { const BufferCopyView* destination, const Extent3D* copySize) { mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - // TODO(dawn:22): Remove once migration from GPUTextureCopyView.arrayLayer to + // TODO(crbug.com/dawn/22): Remove once migration from GPUTextureCopyView.arrayLayer to // GPUTextureCopyView.origin.z is done. TextureCopyView fixedSrc; DAWN_TRY_ASSIGN(fixedSrc, FixTextureCopyView(GetDevice(), source)); source = &fixedSrc; + // TODO(crbug.com/dawn/22): Remove once migration to .layout is done. + BufferCopyView fixedDst; + DAWN_TRY_ASSIGN(fixedDst, FixBufferCopyView(GetDevice(), destination)); + destination = &fixedDst; + if (GetDevice()->IsValidationEnabled()) { DAWN_TRY(ValidateTextureCopyView(GetDevice(), *source)); DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc)); @@ -638,12 +671,7 @@ namespace dawn_native { DAWN_TRY(ValidateBufferCopyView(GetDevice(), *destination)); DAWN_TRY(ValidateCanUseAs(destination->buffer, wgpu::BufferUsage::CopyDst)); - TextureDataLayout dstAsTextureDataLayout; - dstAsTextureDataLayout.offset = destination->offset; - dstAsTextureDataLayout.bytesPerRow = destination->bytesPerRow; - dstAsTextureDataLayout.rowsPerImage = destination->rowsPerImage; - - DAWN_TRY(ValidateLinearTextureData(dstAsTextureDataLayout, + DAWN_TRY(ValidateLinearTextureData(destination->layout, destination->buffer->GetSize(), source->texture->GetFormat(), *copySize)); DAWN_TRY(ValidateTextureCopyRange(*source, *copySize)); @@ -653,7 +681,7 @@ namespace dawn_native { } // Compute default value for rowsPerImage - uint32_t defaultedRowsPerImage = destination->rowsPerImage; + uint32_t defaultedRowsPerImage = destination->layout.rowsPerImage; if (defaultedRowsPerImage == 0) { defaultedRowsPerImage = copySize->height; } @@ -665,8 +693,8 @@ namespace dawn_native { copy->source.origin = source->origin; copy->source.mipLevel = source->mipLevel; copy->destination.buffer = destination->buffer; - copy->destination.offset = destination->offset; - copy->destination.bytesPerRow = destination->bytesPerRow; + copy->destination.offset = destination->layout.offset; + copy->destination.bytesPerRow = destination->layout.bytesPerRow; copy->destination.rowsPerImage = defaultedRowsPerImage; copy->copySize = *copySize; @@ -678,7 +706,7 @@ namespace dawn_native { const TextureCopyView* destination, const Extent3D* copySize) { mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { - // TODO(dawn:22): Remove once migration from GPUTextureCopyView.arrayLayer to + // TODO(crbug.com/dawn/22): Remove once migration from GPUTextureCopyView.arrayLayer to // GPUTextureCopyView.origin.z is done. TextureCopyView fixedSrc; DAWN_TRY_ASSIGN(fixedSrc, FixTextureCopyView(GetDevice(), source)); diff --git a/src/dawn_native/CommandValidation.cpp b/src/dawn_native/CommandValidation.cpp index 019ebb4406..8444655b30 100644 --- a/src/dawn_native/CommandValidation.cpp +++ b/src/dawn_native/CommandValidation.cpp @@ -458,10 +458,15 @@ namespace dawn_native { MaybeError ValidateBufferCopyView(DeviceBase const* device, const BufferCopyView& bufferCopyView) { + // Should have already been fixed up to not use deprecated fields. + ASSERT(bufferCopyView.offset == 0 && bufferCopyView.bytesPerRow == 0 && + bufferCopyView.rowsPerImage == 0); + DAWN_TRY(device->ValidateObject(bufferCopyView.buffer)); - if (bufferCopyView.bytesPerRow % kTextureBytesPerRowAlignment != 0) { + if (bufferCopyView.layout.bytesPerRow % kTextureBytesPerRowAlignment != 0) { return DAWN_VALIDATION_ERROR("bytesPerRow must be a multiple of 256"); } + return {}; } diff --git a/src/dawn_native/CommandValidation.h b/src/dawn_native/CommandValidation.h index 34ff7a41a8..cee2b135a9 100644 --- a/src/dawn_native/CommandValidation.h +++ b/src/dawn_native/CommandValidation.h @@ -48,7 +48,7 @@ namespace dawn_native { const Extent3D& copySize); MaybeError ValidateBufferCopyView(DeviceBase const* device, - const BufferCopyView& bufferCopyView); + const BufferCopyView& bufferCopyViewt); MaybeError ValidateTextureCopyView(DeviceBase const* device, const TextureCopyView& textureCopyView); diff --git a/src/tests/end2end/D3D12ResourceWrappingTests.cpp b/src/tests/end2end/D3D12ResourceWrappingTests.cpp index 364f48fa22..abc86a3522 100644 --- a/src/tests/end2end/D3D12ResourceWrappingTests.cpp +++ b/src/tests/end2end/D3D12ResourceWrappingTests.cpp @@ -266,17 +266,8 @@ class D3D12SharedHandleUsageTests : public D3D12ResourceTestBase { protected: // Submits a 1x1x1 copy from source to destination void SimpleCopyTextureToTexture(wgpu::Texture source, wgpu::Texture destination) { - wgpu::TextureCopyView copySrc; - copySrc.texture = source; - copySrc.mipLevel = 0; - copySrc.arrayLayer = 0; - copySrc.origin = {0, 0, 0}; - - wgpu::TextureCopyView copyDst; - copyDst.texture = destination; - copyDst.mipLevel = 0; - copyDst.arrayLayer = 0; - copyDst.origin = {0, 0, 0}; + wgpu::TextureCopyView copySrc = utils::CreateTextureCopyView(source, 0, {0, 0, 0}); + wgpu::TextureCopyView copyDst = utils::CreateTextureCopyView(destination, 0, {0, 0, 0}); wgpu::Extent3D copySize = {1, 1, 1}; diff --git a/src/tests/end2end/DeprecatedAPITests.cpp b/src/tests/end2end/DeprecatedAPITests.cpp index 2c95929608..312063a5c6 100644 --- a/src/tests/end2end/DeprecatedAPITests.cpp +++ b/src/tests/end2end/DeprecatedAPITests.cpp @@ -173,9 +173,9 @@ class TextureCopyViewArrayLayerDeprecationTests : public DeprecationTests { desc.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst; desc.size = 4; - wgpu::BufferCopyView copy; + wgpu::BufferCopyView copy = {}; copy.buffer = device.CreateBuffer(&desc); - copy.bytesPerRow = kTextureBytesPerRowAlignment; + copy.layout.bytesPerRow = kTextureBytesPerRowAlignment; return copy; } @@ -251,3 +251,115 @@ DAWN_INSTANTIATE_TEST(TextureCopyViewArrayLayerDeprecationTests, NullBackend(), OpenGLBackend(), VulkanBackend()); + +class BufferCopyViewDeprecationTests : public DeprecationTests { + protected: + wgpu::TextureCopyView MakeTextureCopyView() { + wgpu::TextureDescriptor desc = {}; + desc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst; + desc.dimension = wgpu::TextureDimension::e2D; + desc.size = {1, 1, 2}; + desc.format = wgpu::TextureFormat::RGBA8Unorm; + + wgpu::TextureCopyView copy; + copy.texture = device.CreateTexture(&desc); + copy.arrayLayer = 0; + copy.origin = {0, 0, 1}; + return copy; + } + + wgpu::Extent3D copySize = {1, 1, 1}; +}; + +// Test that using BufferCopyView::{offset,bytesPerRow,rowsPerImage} emits a warning. +TEST_P(BufferCopyViewDeprecationTests, DeprecationWarning) { + wgpu::BufferDescriptor desc; + desc.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst; + desc.size = 8; + wgpu::Buffer buffer = device.CreateBuffer(&desc); + + wgpu::TextureCopyView texCopy = MakeTextureCopyView(); + + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + wgpu::BufferCopyView bufCopy = {}; + bufCopy.buffer = buffer; + bufCopy.offset = 4; + EXPECT_DEPRECATION_WARNING(encoder.CopyBufferToTexture(&bufCopy, &texCopy, ©Size)); + EXPECT_DEPRECATION_WARNING(encoder.CopyTextureToBuffer(&texCopy, &bufCopy, ©Size)); + // Since bytesPerRow is 0 + ASSERT_DEVICE_ERROR(encoder.Finish()); + } + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + wgpu::BufferCopyView bufCopy = {}; + bufCopy.buffer = buffer; + bufCopy.bytesPerRow = kTextureBytesPerRowAlignment; + EXPECT_DEPRECATION_WARNING(encoder.CopyBufferToTexture(&bufCopy, &texCopy, ©Size)); + EXPECT_DEPRECATION_WARNING(encoder.CopyTextureToBuffer(&texCopy, &bufCopy, ©Size)); + wgpu::CommandBuffer command = encoder.Finish(); + queue.Submit(1, &command); + } + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + wgpu::BufferCopyView bufCopy = {}; + bufCopy.buffer = buffer; + bufCopy.rowsPerImage = 1; + EXPECT_DEPRECATION_WARNING(encoder.CopyBufferToTexture(&bufCopy, &texCopy, ©Size)); + EXPECT_DEPRECATION_WARNING(encoder.CopyTextureToBuffer(&texCopy, &bufCopy, ©Size)); + // Since bytesPerRow is 0 + ASSERT_DEVICE_ERROR(encoder.Finish()); + } +} + +// Test that using both any old field and any new field is an error +TEST_P(BufferCopyViewDeprecationTests, BothOldAndNew) { + wgpu::BufferDescriptor desc; + desc.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst; + desc.size = 8; + wgpu::Buffer buffer = device.CreateBuffer(&desc); + + wgpu::TextureCopyView texCopy = MakeTextureCopyView(); + + auto testOne = [=](const wgpu::BufferCopyView& bufCopy) { + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyBufferToTexture(&bufCopy, &texCopy, ©Size); + ASSERT_DEVICE_ERROR(encoder.Finish()); + } + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyTextureToBuffer(&texCopy, &bufCopy, ©Size); + ASSERT_DEVICE_ERROR(encoder.Finish()); + } + }; + + { + wgpu::BufferCopyView bufCopy = {}; + bufCopy.buffer = buffer; + bufCopy.layout.bytesPerRow = kTextureBytesPerRowAlignment; + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyBufferToTexture(&bufCopy, &texCopy, ©Size); + encoder.CopyTextureToBuffer(&texCopy, &bufCopy, ©Size); + wgpu::CommandBuffer command = encoder.Finish(); + queue.Submit(1, &command); + } + + bufCopy.offset = 4; + testOne(bufCopy); + bufCopy.offset = 0; + bufCopy.bytesPerRow = kTextureBytesPerRowAlignment; + testOne(bufCopy); + bufCopy.bytesPerRow = 0; + bufCopy.rowsPerImage = 1; + testOne(bufCopy); + } +} + +DAWN_INSTANTIATE_TEST(BufferCopyViewDeprecationTests, + D3D12Backend(), + MetalBackend(), + NullBackend(), + OpenGLBackend(), + VulkanBackend()); diff --git a/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp b/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp index 95d69c1b51..f52b365560 100644 --- a/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp +++ b/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp @@ -313,17 +313,8 @@ namespace dawn_native { namespace vulkan { wgpu::Queue dawnQueue, wgpu::Texture source, wgpu::Texture destination) { - wgpu::TextureCopyView copySrc; - copySrc.texture = source; - copySrc.mipLevel = 0; - copySrc.arrayLayer = 0; - copySrc.origin = {0, 0, 0}; - - wgpu::TextureCopyView copyDst; - copyDst.texture = destination; - copyDst.mipLevel = 0; - copyDst.arrayLayer = 0; - copyDst.origin = {0, 0, 0}; + wgpu::TextureCopyView copySrc = utils::CreateTextureCopyView(source, 0, {0, 0, 0}); + wgpu::TextureCopyView copyDst = utils::CreateTextureCopyView(destination, 0, {0, 0, 0}); wgpu::Extent3D copySize = {1, 1, 1}; @@ -526,17 +517,9 @@ namespace dawn_native { namespace vulkan { wgpu::Buffer copyDstBuffer = device.CreateBuffer(&bufferDesc); // Copy |deviceWrappedTexture| into |copyDstBuffer| - wgpu::TextureCopyView copySrc; - copySrc.texture = deviceWrappedTexture; - copySrc.mipLevel = 0; - copySrc.arrayLayer = 0; - copySrc.origin = {0, 0, 0}; - - wgpu::BufferCopyView copyDst; - copyDst.buffer = copyDstBuffer; - copyDst.offset = 0; - copyDst.bytesPerRow = 256; - copyDst.rowsPerImage = 0; + wgpu::TextureCopyView copySrc = + utils::CreateTextureCopyView(deviceWrappedTexture, 0, {0, 0, 0}); + wgpu::BufferCopyView copyDst = utils::CreateBufferCopyView(copyDstBuffer, 0, 256, 0); wgpu::Extent3D copySize = {1, 1, 1}; @@ -584,17 +567,9 @@ namespace dawn_native { namespace vulkan { utils::CreateBufferFromData(secondDevice, wgpu::BufferUsage::CopySrc, {0x04030201}); // Copy |copySrcBuffer| into |secondDeviceWrappedTexture| - wgpu::BufferCopyView copySrc; - copySrc.buffer = copySrcBuffer; - copySrc.offset = 0; - copySrc.bytesPerRow = 256; - copySrc.rowsPerImage = 0; - - wgpu::TextureCopyView copyDst; - copyDst.texture = secondDeviceWrappedTexture; - copyDst.mipLevel = 0; - copyDst.arrayLayer = 0; - copyDst.origin = {0, 0, 0}; + wgpu::BufferCopyView copySrc = utils::CreateBufferCopyView(copySrcBuffer, 0, 256, 0); + wgpu::TextureCopyView copyDst = + utils::CreateTextureCopyView(secondDeviceWrappedTexture, 0, {0, 0, 0}); wgpu::Extent3D copySize = {1, 1, 1}; diff --git a/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp b/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp index 96471525d6..431bd03c93 100644 --- a/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp +++ b/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp @@ -669,17 +669,9 @@ namespace dawn_native { namespace vulkan { wgpu::Buffer copyDstBuffer = device.CreateBuffer(&bufferDesc); // Copy |deviceWrappedTexture| into |copyDstBuffer| - wgpu::TextureCopyView copySrc; - copySrc.texture = deviceWrappedTexture; - copySrc.mipLevel = 0; - copySrc.arrayLayer = 0; - copySrc.origin = {0, 0, 0}; - - wgpu::BufferCopyView copyDst; - copyDst.buffer = copyDstBuffer; - copyDst.offset = 0; - copyDst.bytesPerRow = 256; - copyDst.rowsPerImage = 0; + wgpu::TextureCopyView copySrc = + utils::CreateTextureCopyView(deviceWrappedTexture, 0, {0, 0, 0}); + wgpu::BufferCopyView copyDst = utils::CreateBufferCopyView(copyDstBuffer, 0, 256, 0); wgpu::Extent3D copySize = {1, 1, 1}; @@ -731,17 +723,9 @@ namespace dawn_native { namespace vulkan { utils::CreateBufferFromData(secondDevice, wgpu::BufferUsage::CopySrc, {0x04030201}); // Copy |copySrcBuffer| into |secondDeviceWrappedTexture| - wgpu::BufferCopyView copySrc; - copySrc.buffer = copySrcBuffer; - copySrc.offset = 0; - copySrc.bytesPerRow = 256; - copySrc.rowsPerImage = 0; - - wgpu::TextureCopyView copyDst; - copyDst.texture = secondDeviceWrappedTexture; - copyDst.mipLevel = 0; - copyDst.arrayLayer = 0; - copyDst.origin = {0, 0, 0}; + wgpu::BufferCopyView copySrc = utils::CreateBufferCopyView(copySrcBuffer, 0, 256, 0); + wgpu::TextureCopyView copyDst = + utils::CreateTextureCopyView(secondDeviceWrappedTexture, 0, {0, 0, 0}); wgpu::Extent3D copySize = {1, 1, 1}; diff --git a/src/utils/WGPUHelpers.cpp b/src/utils/WGPUHelpers.cpp index 3a6b45fb44..f728549307 100644 --- a/src/utils/WGPUHelpers.cpp +++ b/src/utils/WGPUHelpers.cpp @@ -267,11 +267,11 @@ namespace utils { uint64_t offset, uint32_t bytesPerRow, uint32_t rowsPerImage) { - wgpu::BufferCopyView bufferCopyView; + wgpu::BufferCopyView bufferCopyView = {}; bufferCopyView.buffer = buffer; - bufferCopyView.offset = offset; - bufferCopyView.bytesPerRow = bytesPerRow; - bufferCopyView.rowsPerImage = rowsPerImage; + bufferCopyView.layout.offset = offset; + bufferCopyView.layout.bytesPerRow = bytesPerRow; + bufferCopyView.layout.rowsPerImage = rowsPerImage; return bufferCopyView; }