Prevent explicit creation of textures with multiplanar formats Some backend APIs don't let you create multiplanar textures directly. Because we don't need this right now, disallow it. The multiplanar formats feature is restricted to just wrapping external textures now. A separate feature can be added in the future for explicit creation. - moves existing validation tests to end2end tests since we need a backend to wrap yuv textures - hardens validation such that uninitialized multiplanar textures cannot be wrapped. This is because they are currently only valid for readonly usages - meaning Dawn is unable to perform the initialization. Bug: chromium:1450753 Change-Id: I419bee98946ea6d46a938d4379f78691325fbdaf Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/135660 Auto-Submit: Austin Eng <enga@chromium.org> Commit-Queue: Austin Eng <enga@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Jie A Chen <jie.a.chen@intel.com>
diff --git a/src/dawn/native/Texture.cpp b/src/dawn/native/Texture.cpp index 7a72628..9fb485a 100644 --- a/src/dawn/native/Texture.cpp +++ b/src/dawn/native/Texture.cpp
@@ -352,7 +352,8 @@ } // anonymous namespace MaybeError ValidateTextureDescriptor(const DeviceBase* device, - const TextureDescriptor* descriptor) { + const TextureDescriptor* descriptor, + AllowMultiPlanarTextureFormat allowMultiPlanar) { DAWN_TRY(ValidateSingleSType(descriptor->nextInChain, wgpu::SType::DawnTextureInternalUsageDescriptor)); @@ -366,6 +367,16 @@ const Format* format; DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format)); + switch (allowMultiPlanar) { + case AllowMultiPlanarTextureFormat::Yes: + break; + case AllowMultiPlanarTextureFormat::No: + DAWN_INVALID_IF(format->IsMultiPlanar(), + "Creation of multiplanar texture format %s is not allowed.", + descriptor->format); + break; + } + for (uint32_t i = 0; i < descriptor->viewFormatCount; ++i) { DAWN_TRY_CONTEXT( ValidateTextureViewFormatCompatibility(device, *format, descriptor->viewFormats[i]),
diff --git a/src/dawn/native/Texture.h b/src/dawn/native/Texture.h index 781ff60..6914e70 100644 --- a/src/dawn/native/Texture.h +++ b/src/dawn/native/Texture.h
@@ -29,7 +29,15 @@ namespace dawn::native { -MaybeError ValidateTextureDescriptor(const DeviceBase* device, const TextureDescriptor* descriptor); +enum class AllowMultiPlanarTextureFormat { + No, + Yes, +}; + +MaybeError ValidateTextureDescriptor( + const DeviceBase* device, + const TextureDescriptor* descriptor, + AllowMultiPlanarTextureFormat allowMultiPlanar = AllowMultiPlanarTextureFormat::No); MaybeError ValidateTextureViewDescriptor(const DeviceBase* device, const TextureBase* texture, const TextureViewDescriptor* descriptor);
diff --git a/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp b/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp index 1c7885d..8c26b2a 100644 --- a/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp +++ b/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp
@@ -116,6 +116,13 @@ } ASSERT(mBackendDevice != nullptr); + if (mBackendDevice->GetValidInternalFormat(mFormat).IsMultiPlanar() && + !descriptor->isInitialized) { + bool consumed = mBackendDevice->ConsumedError(DAWN_VALIDATION_ERROR( + "External textures with multiplanar formats must be initialized.")); + DAWN_UNUSED(consumed); + return nullptr; + } TextureDescriptor textureDescriptor = {}; textureDescriptor.usage = static_cast<wgpu::TextureUsage>(descriptor->usage);
diff --git a/src/dawn/native/d3d11/DeviceD3D11.cpp b/src/dawn/native/d3d11/DeviceD3D11.cpp index 0d7d9d1..1367a28 100644 --- a/src/dawn/native/d3d11/DeviceD3D11.cpp +++ b/src/dawn/native/d3d11/DeviceD3D11.cpp
@@ -418,7 +418,8 @@ "D3D11 OpenSharedResource1")); const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor); - DAWN_TRY(ValidateTextureDescriptor(this, textureDescriptor)); + DAWN_TRY( + ValidateTextureDescriptor(this, textureDescriptor, AllowMultiPlanarTextureFormat::Yes)); DAWN_TRY_CONTEXT(d3d::ValidateTextureDescriptorCanBeWrapped(textureDescriptor), "validating that a D3D11 external image can be wrapped with %s",
diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp index d1088b7..415903f 100644 --- a/src/dawn/native/d3d12/DeviceD3D12.cpp +++ b/src/dawn/native/d3d12/DeviceD3D12.cpp
@@ -553,7 +553,8 @@ const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor); - DAWN_TRY(ValidateTextureDescriptor(this, textureDescriptor)); + DAWN_TRY( + ValidateTextureDescriptor(this, textureDescriptor, AllowMultiPlanarTextureFormat::Yes)); DAWN_TRY_CONTEXT(d3d::ValidateTextureDescriptorCanBeWrapped(textureDescriptor), "validating that a D3D12 external image can be wrapped with %s",
diff --git a/src/dawn/native/metal/DeviceMTL.mm b/src/dawn/native/metal/DeviceMTL.mm index f59de4b..b82c167 100644 --- a/src/dawn/native/metal/DeviceMTL.mm +++ b/src/dawn/native/metal/DeviceMTL.mm
@@ -426,12 +426,20 @@ if (ConsumedError(ValidateIsAlive())) { return nullptr; } - if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor))) { + if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor, + AllowMultiPlanarTextureFormat::Yes))) { return nullptr; } if (ConsumedError(ValidateIOSurfaceCanBeWrapped(this, textureDescriptor, ioSurface))) { return nullptr; } + if (GetValidInternalFormat(textureDescriptor->format).IsMultiPlanar() && + !descriptor->isInitialized) { + bool consumed = ConsumedError(DAWN_VALIDATION_ERROR( + "External textures with multiplanar formats must be initialized.")); + DAWN_UNUSED(consumed); + return nullptr; + } Ref<Texture> result; if (ConsumedError(
diff --git a/src/dawn/native/vulkan/DeviceVk.cpp b/src/dawn/native/vulkan/DeviceVk.cpp index a58e907..0dae3fa 100644 --- a/src/dawn/native/vulkan/DeviceVk.cpp +++ b/src/dawn/native/vulkan/DeviceVk.cpp
@@ -882,7 +882,8 @@ if (ConsumedError(ValidateIsAlive())) { return nullptr; } - if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor))) { + if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor, + AllowMultiPlanarTextureFormat::Yes))) { return nullptr; } if (ConsumedError(ValidateVulkanImageCanBeWrapped(this, textureDescriptor), @@ -890,6 +891,13 @@ textureDescriptor)) { return nullptr; } + if (GetValidInternalFormat(textureDescriptor->format).IsMultiPlanar() && + !descriptor->isInitialized) { + bool consumed = ConsumedError(DAWN_VALIDATION_ERROR( + "External textures with multiplanar formats must be initialized.")); + DAWN_UNUSED(consumed); + return nullptr; + } VkDeviceMemory allocation = VK_NULL_HANDLE; std::vector<VkSemaphore> waitSemaphores;
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn index 4760567..1f7b5aa 100644 --- a/src/dawn/tests/BUILD.gn +++ b/src/dawn/tests/BUILD.gn
@@ -368,7 +368,6 @@ "unittests/validation/ValidationTest.h", "unittests/validation/VertexBufferValidationTests.cpp", "unittests/validation/VertexStateValidationTests.cpp", - "unittests/validation/VideoViewsValidationTests.cpp", "unittests/validation/WritableBufferBindingAliasingValidationTests.cpp", "unittests/validation/WritableTextureBindingAliasingValidationTests.cpp", "unittests/validation/WriteBufferTests.cpp",
diff --git a/src/dawn/tests/end2end/VideoViewsTests.cpp b/src/dawn/tests/end2end/VideoViewsTests.cpp index dc0e5b1..97942e5 100644 --- a/src/dawn/tests/end2end/VideoViewsTests.cpp +++ b/src/dawn/tests/end2end/VideoViewsTests.cpp
@@ -211,12 +211,12 @@ // Create video texture uninitialized. TEST_P(VideoViewsTests, CreateVideoTextureWithoutInitializedData) { - std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture = - mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding, - /*isCheckerboard*/ false, - /*initialized*/ false); - ASSERT_NE(platformTexture.get(), nullptr); + ASSERT_DEVICE_ERROR( + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ false, + /*initialized*/ false)); mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); } @@ -489,7 +489,406 @@ mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); } +class VideoViewsValidationTests : public VideoViewsTests { + protected: + void SetUp() override { + VideoViewsTests::SetUp(); + DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation")); + } +}; + +// Test explicitly creating a multiplanar format is not allowed +TEST_P(VideoViewsValidationTests, ExplicitCreation) { + wgpu::TextureDescriptor descriptor; + descriptor.dimension = wgpu::TextureDimension::e2D; + descriptor.size.width = 1; + descriptor.size.height = 1; + descriptor.format = wgpu::TextureFormat::R8BG8Biplanar420Unorm; + descriptor.usage = wgpu::TextureUsage::TextureBinding; + ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor)); +} + +// Test texture view creation rules. +TEST_P(VideoViewsValidationTests, CreateViewValidation) { + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + ASSERT_NE(platformTexture.get(), nullptr); + if (!platformTexture->CanWrapAsWGPUTexture()) { + mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); + GTEST_SKIP() << "Skipped because not supported."; + } + + wgpu::TextureViewDescriptor viewDesc = {}; + + // Success case: Per plane view formats unspecified. + { + viewDesc.aspect = wgpu::TextureAspect::Plane0Only; + wgpu::TextureView plane0View = platformTexture->wgpuTexture.CreateView(&viewDesc); + + viewDesc.aspect = wgpu::TextureAspect::Plane1Only; + wgpu::TextureView plane1View = platformTexture->wgpuTexture.CreateView(&viewDesc); + + ASSERT_NE(plane0View.Get(), nullptr); + ASSERT_NE(plane1View.Get(), nullptr); + } + + // Success case: Per plane view formats specified and aspect. + { + viewDesc.aspect = wgpu::TextureAspect::Plane0Only; + viewDesc.format = wgpu::TextureFormat::R8Unorm; + wgpu::TextureView plane0View = platformTexture->wgpuTexture.CreateView(&viewDesc); + + viewDesc.aspect = wgpu::TextureAspect::Plane1Only; + viewDesc.format = wgpu::TextureFormat::RG8Unorm; + wgpu::TextureView plane1View = platformTexture->wgpuTexture.CreateView(&viewDesc); + + ASSERT_NE(plane0View.Get(), nullptr); + ASSERT_NE(plane1View.Get(), nullptr); + } + + // Some valid view format, but no plane specified. + viewDesc = {}; + viewDesc.format = wgpu::TextureFormat::R8Unorm; + ASSERT_DEVICE_ERROR(platformTexture->wgpuTexture.CreateView(&viewDesc)); + + // Some valid view format, but no plane specified. + viewDesc = {}; + viewDesc.format = wgpu::TextureFormat::RG8Unorm; + ASSERT_DEVICE_ERROR(platformTexture->wgpuTexture.CreateView(&viewDesc)); + + // Correct plane index but incompatible view format. + viewDesc.format = wgpu::TextureFormat::R8Uint; + viewDesc.aspect = wgpu::TextureAspect::Plane0Only; + ASSERT_DEVICE_ERROR(platformTexture->wgpuTexture.CreateView(&viewDesc)); + + // Compatible view format but wrong plane index. + viewDesc.format = wgpu::TextureFormat::R8Unorm; + viewDesc.aspect = wgpu::TextureAspect::Plane1Only; + ASSERT_DEVICE_ERROR(platformTexture->wgpuTexture.CreateView(&viewDesc)); + + // Compatible view format but wrong aspect. + viewDesc.format = wgpu::TextureFormat::R8Unorm; + viewDesc.aspect = wgpu::TextureAspect::All; + ASSERT_DEVICE_ERROR(platformTexture->wgpuTexture.CreateView(&viewDesc)); + + // Create a single plane texture. + wgpu::TextureDescriptor desc; + desc.format = wgpu::TextureFormat::RGBA8Unorm; + desc.dimension = wgpu::TextureDimension::e2D; + desc.usage = wgpu::TextureUsage::TextureBinding; + desc.size = {1, 1, 1}; + + wgpu::Texture texture = device.CreateTexture(&desc); + + // Plane aspect specified with non-planar texture. + viewDesc.aspect = wgpu::TextureAspect::Plane0Only; + ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc)); + + viewDesc.aspect = wgpu::TextureAspect::Plane1Only; + ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc)); + + // Planar views with non-planar texture. + viewDesc.aspect = wgpu::TextureAspect::Plane0Only; + viewDesc.format = wgpu::TextureFormat::R8Unorm; + ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc)); + + viewDesc.aspect = wgpu::TextureAspect::Plane1Only; + viewDesc.format = wgpu::TextureFormat::RG8Unorm; + ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc)); + + mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); +} + +// Test copying from one multi-planar format into another fails. +TEST_P(VideoViewsValidationTests, T2TCopyAllAspectsFails) { + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture1 = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture2 = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + + wgpu::Texture srcTexture = platformTexture1->wgpuTexture; + wgpu::Texture dstTexture = platformTexture2->wgpuTexture; + + wgpu::ImageCopyTexture copySrc = utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}); + + wgpu::ImageCopyTexture copyDst = utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}); + + wgpu::Extent3D copySize = {1, 1, 1}; + + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyTextureToTexture(©Src, ©Dst, ©Size); + ASSERT_DEVICE_ERROR(encoder.Finish()); + + mBackend->DestroyVideoTextureForTest(std::move(platformTexture1)); + mBackend->DestroyVideoTextureForTest(std::move(platformTexture2)); +} + +// Test copying from one multi-planar format into another per plane fails. +TEST_P(VideoViewsValidationTests, T2TCopyPlaneAspectFails) { + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture1 = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture2 = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + + wgpu::Texture srcTexture = platformTexture1->wgpuTexture; + wgpu::Texture dstTexture = platformTexture2->wgpuTexture; + + wgpu::ImageCopyTexture copySrc = + utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only); + + wgpu::ImageCopyTexture copyDst = + utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane1Only); + + wgpu::Extent3D copySize = {1, 1, 1}; + + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyTextureToTexture(©Src, ©Dst, ©Size); + ASSERT_DEVICE_ERROR(encoder.Finish()); + } + + copySrc = + utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane1Only); + + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyTextureToTexture(©Src, ©Dst, ©Size); + ASSERT_DEVICE_ERROR(encoder.Finish()); + } + + mBackend->DestroyVideoTextureForTest(std::move(platformTexture1)); + mBackend->DestroyVideoTextureForTest(std::move(platformTexture2)); +} + +// Test copying from a multi-planar format to a buffer fails. +TEST_P(VideoViewsValidationTests, T2BCopyAllAspectsFails) { + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + wgpu::Texture srcTexture = platformTexture->wgpuTexture; + + wgpu::BufferDescriptor bufferDescriptor; + bufferDescriptor.size = 1; + bufferDescriptor.usage = wgpu::BufferUsage::CopyDst; + wgpu::Buffer dstBuffer = device.CreateBuffer(&bufferDescriptor); + + wgpu::ImageCopyTexture copySrc = utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}); + + wgpu::ImageCopyBuffer copyDst = utils::CreateImageCopyBuffer(dstBuffer, 0, 4); + + wgpu::Extent3D copySize = {1, 1, 1}; + + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyTextureToBuffer(©Src, ©Dst, ©Size); + ASSERT_DEVICE_ERROR(encoder.Finish()); + + mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); +} + +// Test copying from multi-planar format per plane to a buffer fails. +TEST_P(VideoViewsValidationTests, T2BCopyPlaneAspectsFails) { + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + wgpu::Texture srcTexture = platformTexture->wgpuTexture; + + wgpu::BufferDescriptor bufferDescriptor; + bufferDescriptor.size = 1; + bufferDescriptor.usage = wgpu::BufferUsage::CopyDst; + wgpu::Buffer dstBuffer = device.CreateBuffer(&bufferDescriptor); + + wgpu::ImageCopyTexture copySrc = + utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only); + + wgpu::ImageCopyBuffer copyDst = utils::CreateImageCopyBuffer(dstBuffer, 0, 4); + + wgpu::Extent3D copySize = {1, 1, 1}; + + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyTextureToBuffer(©Src, ©Dst, ©Size); + ASSERT_DEVICE_ERROR(encoder.Finish()); + } + + copySrc = + utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane1Only); + + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyTextureToBuffer(©Src, ©Dst, ©Size); + ASSERT_DEVICE_ERROR(encoder.Finish()); + } + + mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); +} + +// Test copying from a buffer to a multi-planar format fails. +TEST_P(VideoViewsValidationTests, B2TCopyAllAspectsFails) { + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + wgpu::Texture dstTexture = platformTexture->wgpuTexture; + + std::vector<uint8_t> placeholderData(4, 0); + + wgpu::Buffer srcBuffer = utils::CreateBufferFromData( + device, placeholderData.data(), placeholderData.size(), wgpu::BufferUsage::CopySrc); + + wgpu::ImageCopyBuffer copySrc = utils::CreateImageCopyBuffer(srcBuffer, 0, 12, 4); + + wgpu::ImageCopyTexture copyDst = utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}); + + wgpu::Extent3D copySize = {1, 1, 1}; + + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyBufferToTexture(©Src, ©Dst, ©Size); + ASSERT_DEVICE_ERROR(encoder.Finish()); + + mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); +} + +// Test copying from a buffer to a multi-planar format per plane fails. +TEST_P(VideoViewsValidationTests, B2TCopyPlaneAspectsFails) { + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + wgpu::Texture dstTexture = platformTexture->wgpuTexture; + + std::vector<uint8_t> placeholderData(4, 0); + + wgpu::Buffer srcBuffer = utils::CreateBufferFromData( + device, placeholderData.data(), placeholderData.size(), wgpu::BufferUsage::CopySrc); + + wgpu::ImageCopyBuffer copySrc = utils::CreateImageCopyBuffer(srcBuffer, 0, 12, 4); + + wgpu::ImageCopyTexture copyDst = + utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only); + + wgpu::Extent3D copySize = {1, 1, 1}; + + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyBufferToTexture(©Src, ©Dst, ©Size); + ASSERT_DEVICE_ERROR(encoder.Finish()); + } + + copyDst = + utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane1Only); + + { + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyBufferToTexture(©Src, ©Dst, ©Size); + ASSERT_DEVICE_ERROR(encoder.Finish()); + } + mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); +} + +// Tests which multi-planar formats are allowed to be sampled. +TEST_P(VideoViewsValidationTests, SamplingMultiPlanarTexture) { + wgpu::BindGroupLayout layout = utils::MakeBindGroupLayout( + device, {{0, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Float}}); + + // R8BG8Biplanar420Unorm is allowed to be sampled, if plane 0 or plane 1 is selected. + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + + wgpu::TextureViewDescriptor desc = {}; + + desc.aspect = wgpu::TextureAspect::Plane0Only; + utils::MakeBindGroup(device, layout, {{0, platformTexture->wgpuTexture.CreateView(&desc)}}); + + desc.aspect = wgpu::TextureAspect::Plane1Only; + utils::MakeBindGroup(device, layout, {{0, platformTexture->wgpuTexture.CreateView(&desc)}}); + + mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); +} + +// Tests creating a texture with a multi-plane format. +TEST_P(VideoViewsValidationTests, RenderAttachmentInvalid) { + // multi-planar formats are NOT allowed to be renderable. + ASSERT_DEVICE_ERROR(auto platformTexture = mBackend->CreateVideoTextureForTest( + wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::RenderAttachment, + /*isCheckerboard*/ true, + /*initialized*/ true)); + mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); +} + +// Tests writing into a multi-planar format fails. +TEST_P(VideoViewsValidationTests, WriteTextureAllAspectsFails) { + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + + wgpu::TextureDataLayout textureDataLayout = utils::CreateTextureDataLayout(0, 4, 4); + + wgpu::ImageCopyTexture imageCopyTexture = + utils::CreateImageCopyTexture(platformTexture->wgpuTexture, 0, {0, 0, 0}); + + std::vector<uint8_t> placeholderData(4, 0); + wgpu::Extent3D writeSize = {1, 1, 1}; + + wgpu::Queue queue = device.GetQueue(); + + ASSERT_DEVICE_ERROR(queue.WriteTexture(&imageCopyTexture, placeholderData.data(), + placeholderData.size(), &textureDataLayout, &writeSize)); + mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); +} + +// Tests writing into a multi-planar format per plane fails. +TEST_P(VideoViewsValidationTests, WriteTexturePlaneAspectsFails) { + std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture = + mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding, + /*isCheckerboard*/ true, + /*initialized*/ true); + + wgpu::TextureDataLayout textureDataLayout = utils::CreateTextureDataLayout(0, 12, 4); + wgpu::ImageCopyTexture imageCopyTexture = utils::CreateImageCopyTexture( + platformTexture->wgpuTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only); + + std::vector<uint8_t> placeholderData(4, 0); + wgpu::Extent3D writeSize = {1, 1, 1}; + + wgpu::Queue queue = device.GetQueue(); + + ASSERT_DEVICE_ERROR(queue.WriteTexture(&imageCopyTexture, placeholderData.data(), + placeholderData.size(), &textureDataLayout, &writeSize)); + mBackend->DestroyVideoTextureForTest(std::move(platformTexture)); +} + DAWN_INSTANTIATE_TEST_V(VideoViewsTests, VideoViewsTestBackend::Backends()); +DAWN_INSTANTIATE_TEST_V(VideoViewsValidationTests, VideoViewsTestBackend::Backends()); } // anonymous namespace } // namespace dawn
diff --git a/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp b/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp index eac747c..8de4141 100644 --- a/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp +++ b/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp
@@ -184,7 +184,7 @@ native::vulkan::ExternalImageDescriptorDmaBuf descriptor = {}; descriptor.cTextureDescriptor = reinterpret_cast<const WGPUTextureDescriptor*>(&textureDesc); - descriptor.isInitialized = true; + descriptor.isInitialized = initialized; descriptor.memoryFD = gbm_bo_get_fd(gbmBo); for (int plane = 0; plane < gbm_bo_get_plane_count(gbmBo); ++plane) { @@ -194,12 +194,8 @@ descriptor.drmModifier = gbm_bo_get_modifier(gbmBo); descriptor.waitFDs = {}; - WGPUTexture texture = native::vulkan::WrapVulkanImage(mWGPUDevice, &descriptor); - if (texture != nullptr) { - return std::make_unique<PlatformTextureGbm>(wgpu::Texture::Acquire(texture), gbmBo); - } else { - return nullptr; - } + return std::make_unique<PlatformTextureGbm>( + native::vulkan::WrapVulkanImage(mWGPUDevice, &descriptor), gbmBo); } void DestroyVideoTextureForTest(
diff --git a/src/dawn/tests/end2end/VideoViewsTests_mac.cpp b/src/dawn/tests/end2end/VideoViewsTests_mac.cpp index a6d1cf4..b1eb583 100644 --- a/src/dawn/tests/end2end/VideoViewsTests_mac.cpp +++ b/src/dawn/tests/end2end/VideoViewsTests_mac.cpp
@@ -161,7 +161,7 @@ native::metal::ExternalImageDescriptorIOSurface descriptor = {}; descriptor.cTextureDescriptor = reinterpret_cast<const WGPUTextureDescriptor*>(&textureDesc); - descriptor.isInitialized = true; + descriptor.isInitialized = initialized; descriptor.ioSurface = surface; return std::make_unique<PlatformTextureIOSurface>(
diff --git a/src/dawn/tests/end2end/VideoViewsTests_win.cpp b/src/dawn/tests/end2end/VideoViewsTests_win.cpp index 82040c6..f505716 100644 --- a/src/dawn/tests/end2end/VideoViewsTests_win.cpp +++ b/src/dawn/tests/end2end/VideoViewsTests_win.cpp
@@ -175,12 +175,19 @@ // Handle is no longer needed once resources are created. ::CloseHandle(sharedHandle); + if (!externalImage) { + // Failed to create external image. Return early and close outstanding handles. + // Otherwise we'll dereference a nullptr below. + ::CloseHandle(fenceSharedHandle); + return nullptr; + } + native::d3d::ExternalImageDXGIFenceDescriptor fenceDesc; fenceDesc.fenceHandle = fenceSharedHandle; fenceDesc.fenceValue = 1; native::d3d::ExternalImageDXGIBeginAccessDescriptor externalAccessDesc; - externalAccessDesc.isInitialized = true; + externalAccessDesc.isInitialized = initialized; externalAccessDesc.usage = static_cast<WGPUTextureUsageFlags>(textureDesc.usage); externalAccessDesc.waitFences = {};
diff --git a/src/dawn/tests/unittests/validation/VideoViewsValidationTests.cpp b/src/dawn/tests/unittests/validation/VideoViewsValidationTests.cpp deleted file mode 100644 index 57c17e7..0000000 --- a/src/dawn/tests/unittests/validation/VideoViewsValidationTests.cpp +++ /dev/null
@@ -1,342 +0,0 @@ -// 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 <vector> - -#include "dawn/tests/unittests/validation/ValidationTest.h" -#include "dawn/utils/WGPUHelpers.h" - -namespace dawn { -namespace { - -class VideoViewsValidation : public ValidationTest { - protected: - WGPUDevice CreateTestDevice(native::Adapter dawnAdapter, - wgpu::DeviceDescriptor descriptor) override { - wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::DawnMultiPlanarFormats}; - descriptor.requiredFeatures = requiredFeatures; - descriptor.requiredFeaturesCount = 1; - return dawnAdapter.CreateDevice(&descriptor); - } - - wgpu::Texture CreateVideoTextureForTest(wgpu::TextureFormat format, wgpu::TextureUsage usage) { - wgpu::TextureDescriptor descriptor; - descriptor.dimension = wgpu::TextureDimension::e2D; - descriptor.size.width = 1; - descriptor.size.height = 1; - descriptor.format = format; - descriptor.usage = usage; - return device.CreateTexture(&descriptor); - } -}; - -// Test texture views compatibility rules. -TEST_F(VideoViewsValidation, CreateViewFails) { - wgpu::Texture videoTexture = CreateVideoTextureForTest( - wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding); - - wgpu::TextureViewDescriptor viewDesc = {}; - - // Correct plane index but incompatible view format. - viewDesc.format = wgpu::TextureFormat::R8Uint; - viewDesc.aspect = wgpu::TextureAspect::Plane0Only; - ASSERT_DEVICE_ERROR(videoTexture.CreateView(&viewDesc)); - - // Compatible view format but wrong plane index. - viewDesc.format = wgpu::TextureFormat::R8Unorm; - viewDesc.aspect = wgpu::TextureAspect::Plane1Only; - ASSERT_DEVICE_ERROR(videoTexture.CreateView(&viewDesc)); - - // Compatible view format but wrong aspect. - viewDesc.format = wgpu::TextureFormat::R8Unorm; - viewDesc.aspect = wgpu::TextureAspect::All; - ASSERT_DEVICE_ERROR(videoTexture.CreateView(&viewDesc)); - - // Create a single plane texture. - wgpu::TextureDescriptor desc; - desc.format = wgpu::TextureFormat::RGBA8Unorm; - desc.dimension = wgpu::TextureDimension::e2D; - desc.usage = wgpu::TextureUsage::TextureBinding; - desc.size = {1, 1, 1}; - - wgpu::Texture texture = device.CreateTexture(&desc); - - // Plane aspect specified with non-planar texture. - viewDesc.aspect = wgpu::TextureAspect::Plane0Only; - ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc)); - - viewDesc.aspect = wgpu::TextureAspect::Plane1Only; - ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc)); - - // Planar views with non-planar texture. - viewDesc.aspect = wgpu::TextureAspect::Plane0Only; - viewDesc.format = wgpu::TextureFormat::R8Unorm; - ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc)); - - viewDesc.aspect = wgpu::TextureAspect::Plane1Only; - viewDesc.format = wgpu::TextureFormat::RG8Unorm; - ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc)); -} - -// Test texture views compatibility rules. -TEST_F(VideoViewsValidation, CreateViewSucceeds) { - wgpu::Texture yuvTexture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - // Per plane view formats unspecified. - wgpu::TextureViewDescriptor planeViewDesc = {}; - planeViewDesc.aspect = wgpu::TextureAspect::Plane0Only; - wgpu::TextureView plane0View = yuvTexture.CreateView(&planeViewDesc); - - planeViewDesc.aspect = wgpu::TextureAspect::Plane1Only; - wgpu::TextureView plane1View = yuvTexture.CreateView(&planeViewDesc); - - ASSERT_NE(plane0View.Get(), nullptr); - ASSERT_NE(plane1View.Get(), nullptr); - - // Per plane view formats specified. - planeViewDesc.aspect = wgpu::TextureAspect::Plane0Only; - planeViewDesc.format = wgpu::TextureFormat::R8Unorm; - plane0View = yuvTexture.CreateView(&planeViewDesc); - - planeViewDesc.aspect = wgpu::TextureAspect::Plane1Only; - planeViewDesc.format = wgpu::TextureFormat::RG8Unorm; - plane1View = yuvTexture.CreateView(&planeViewDesc); - - ASSERT_NE(plane0View.Get(), nullptr); - ASSERT_NE(plane1View.Get(), nullptr); -} - -// Test copying from one multi-planar format into another fails. -TEST_F(VideoViewsValidation, T2TCopyAllAspectsFails) { - wgpu::Texture srcTexture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - wgpu::Texture dstTexture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - wgpu::ImageCopyTexture copySrc = utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}); - - wgpu::ImageCopyTexture copyDst = utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}); - - wgpu::Extent3D copySize = {1, 1, 1}; - - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - encoder.CopyTextureToTexture(©Src, ©Dst, ©Size); - ASSERT_DEVICE_ERROR(encoder.Finish()); -} - -// Test copying from one multi-planar format into another per plane fails. -TEST_F(VideoViewsValidation, T2TCopyPlaneAspectFails) { - wgpu::Texture srcTexture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - wgpu::Texture dstTexture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - wgpu::ImageCopyTexture copySrc = - utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only); - - wgpu::ImageCopyTexture copyDst = - utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane1Only); - - wgpu::Extent3D copySize = {1, 1, 1}; - - { - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - encoder.CopyTextureToTexture(©Src, ©Dst, ©Size); - ASSERT_DEVICE_ERROR(encoder.Finish()); - } - - copySrc = - utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane1Only); - - { - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - encoder.CopyTextureToTexture(©Src, ©Dst, ©Size); - ASSERT_DEVICE_ERROR(encoder.Finish()); - } -} - -// Test copying from a multi-planar format to a buffer fails. -TEST_F(VideoViewsValidation, T2BCopyAllAspectsFails) { - wgpu::Texture srcTexture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - wgpu::BufferDescriptor bufferDescriptor; - bufferDescriptor.size = 1; - bufferDescriptor.usage = wgpu::BufferUsage::CopyDst; - wgpu::Buffer dstBuffer = device.CreateBuffer(&bufferDescriptor); - - wgpu::ImageCopyTexture copySrc = utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}); - - wgpu::ImageCopyBuffer copyDst = utils::CreateImageCopyBuffer(dstBuffer, 0, 4); - - wgpu::Extent3D copySize = {1, 1, 1}; - - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - encoder.CopyTextureToBuffer(©Src, ©Dst, ©Size); - ASSERT_DEVICE_ERROR(encoder.Finish()); -} - -// Test copying from multi-planar format per plane to a buffer fails. -TEST_F(VideoViewsValidation, T2BCopyPlaneAspectsFails) { - wgpu::Texture srcTexture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - wgpu::BufferDescriptor bufferDescriptor; - bufferDescriptor.size = 1; - bufferDescriptor.usage = wgpu::BufferUsage::CopyDst; - wgpu::Buffer dstBuffer = device.CreateBuffer(&bufferDescriptor); - - wgpu::ImageCopyTexture copySrc = - utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only); - - wgpu::ImageCopyBuffer copyDst = utils::CreateImageCopyBuffer(dstBuffer, 0, 4); - - wgpu::Extent3D copySize = {1, 1, 1}; - - { - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - encoder.CopyTextureToBuffer(©Src, ©Dst, ©Size); - ASSERT_DEVICE_ERROR(encoder.Finish()); - } - - copySrc = - utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane1Only); - - { - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - encoder.CopyTextureToBuffer(©Src, ©Dst, ©Size); - ASSERT_DEVICE_ERROR(encoder.Finish()); - } -} - -// Test copying from a buffer to a multi-planar format fails. -TEST_F(VideoViewsValidation, B2TCopyAllAspectsFails) { - std::vector<uint8_t> placeholderData(4, 0); - - wgpu::Buffer srcBuffer = utils::CreateBufferFromData( - device, placeholderData.data(), placeholderData.size(), wgpu::BufferUsage::CopySrc); - - wgpu::Texture dstTexture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - wgpu::ImageCopyBuffer copySrc = utils::CreateImageCopyBuffer(srcBuffer, 0, 12, 4); - - wgpu::ImageCopyTexture copyDst = utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}); - - wgpu::Extent3D copySize = {1, 1, 1}; - - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - encoder.CopyBufferToTexture(©Src, ©Dst, ©Size); - ASSERT_DEVICE_ERROR(encoder.Finish()); -} - -// Test copying from a buffer to a multi-planar format per plane fails. -TEST_F(VideoViewsValidation, B2TCopyPlaneAspectsFails) { - std::vector<uint8_t> placeholderData(4, 0); - - wgpu::Buffer srcBuffer = utils::CreateBufferFromData( - device, placeholderData.data(), placeholderData.size(), wgpu::BufferUsage::CopySrc); - - wgpu::Texture dstTexture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - wgpu::ImageCopyBuffer copySrc = utils::CreateImageCopyBuffer(srcBuffer, 0, 12, 4); - - wgpu::ImageCopyTexture copyDst = - utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only); - - wgpu::Extent3D copySize = {1, 1, 1}; - - { - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - encoder.CopyBufferToTexture(©Src, ©Dst, ©Size); - ASSERT_DEVICE_ERROR(encoder.Finish()); - } - - copyDst = - utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane1Only); - - { - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - encoder.CopyBufferToTexture(©Src, ©Dst, ©Size); - ASSERT_DEVICE_ERROR(encoder.Finish()); - } -} - -// Tests which multi-planar formats are allowed to be sampled. -TEST_F(VideoViewsValidation, SamplingMultiPlanarTexture) { - wgpu::BindGroupLayout layout = utils::MakeBindGroupLayout( - device, {{0, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Float}}); - - // R8BG8Biplanar420Unorm is allowed to be sampled, if plane 0 or plane 1 is selected. - wgpu::Texture texture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - wgpu::TextureViewDescriptor desc = {}; - - desc.aspect = wgpu::TextureAspect::Plane0Only; - utils::MakeBindGroup(device, layout, {{0, texture.CreateView(&desc)}}); - - desc.aspect = wgpu::TextureAspect::Plane1Only; - utils::MakeBindGroup(device, layout, {{0, texture.CreateView(&desc)}}); -} - -// Tests creating a texture with a multi-plane format. -TEST_F(VideoViewsValidation, CreateTextureFails) { - // multi-planar formats are NOT allowed to be renderable. - ASSERT_DEVICE_ERROR(CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::RenderAttachment)); -} - -// Tests writing into a multi-planar format fails. -TEST_F(VideoViewsValidation, WriteTextureAllAspectsFails) { - wgpu::Texture texture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - wgpu::TextureDataLayout textureDataLayout = utils::CreateTextureDataLayout(0, 4, 4); - - wgpu::ImageCopyTexture imageCopyTexture = utils::CreateImageCopyTexture(texture, 0, {0, 0, 0}); - - std::vector<uint8_t> placeholderData(4, 0); - wgpu::Extent3D writeSize = {1, 1, 1}; - - wgpu::Queue queue = device.GetQueue(); - - ASSERT_DEVICE_ERROR(queue.WriteTexture(&imageCopyTexture, placeholderData.data(), - placeholderData.size(), &textureDataLayout, &writeSize)); -} - -// Tests writing into a multi-planar format per plane fails. -TEST_F(VideoViewsValidation, WriteTexturePlaneAspectsFails) { - wgpu::Texture texture = CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm, - wgpu::TextureUsage::TextureBinding); - - wgpu::TextureDataLayout textureDataLayout = utils::CreateTextureDataLayout(0, 12, 4); - wgpu::ImageCopyTexture imageCopyTexture = - utils::CreateImageCopyTexture(texture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only); - - std::vector<uint8_t> placeholderData(4, 0); - wgpu::Extent3D writeSize = {1, 1, 1}; - - wgpu::Queue queue = device.GetQueue(); - - ASSERT_DEVICE_ERROR(queue.WriteTexture(&imageCopyTexture, placeholderData.data(), - placeholderData.size(), &textureDataLayout, &writeSize)); -} - -} // anonymous namespace -} // namespace dawn