Remove WrapIOSurface()
Chromium no longer uses this API - it nows uses SharedTextureMemory on
Apple platforms.
Bug: dawn:2299
Change-Id: I336d2ec9ce23a5869d456cccee8f7808247f6ef9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/166260
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Colin Blundell <blundell@chromium.org>
diff --git a/include/dawn/native/MetalBackend.h b/include/dawn/native/MetalBackend.h
index ccf89c9..c07349a 100644
--- a/include/dawn/native/MetalBackend.h
+++ b/include/dawn/native/MetalBackend.h
@@ -80,9 +80,6 @@
bool isInitialized;
};
-DAWN_NATIVE_EXPORT WGPUTexture WrapIOSurface(WGPUDevice device,
- const ExternalImageDescriptorIOSurface* descriptor);
-
DAWN_NATIVE_EXPORT void IOSurfaceEndAccess(WGPUTexture texture,
ExternalImageIOSurfaceEndAccessDescriptor* descriptor);
diff --git a/src/dawn/native/metal/BackendMTL.mm b/src/dawn/native/metal/BackendMTL.mm
index 6abf054..8df96d4 100644
--- a/src/dawn/native/metal/BackendMTL.mm
+++ b/src/dawn/native/metal/BackendMTL.mm
@@ -298,8 +298,8 @@
// PhysicalDeviceBase Implementation
bool SupportsExternalImages() const override {
- // Via dawn::native::metal::WrapIOSurface
- return true;
+ // SharedTextureMemory is the supported means of importing IOSurfaces.
+ return false;
}
bool SupportsFeatureLevel(FeatureLevel) const override { return true; }
diff --git a/src/dawn/native/metal/MetalBackend.mm b/src/dawn/native/metal/MetalBackend.mm
index 00a6d21..87b71ea 100644
--- a/src/dawn/native/metal/MetalBackend.mm
+++ b/src/dawn/native/metal/MetalBackend.mm
@@ -41,19 +41,6 @@
ExternalImageDescriptorIOSurface::~ExternalImageDescriptorIOSurface() = default;
-WGPUTexture WrapIOSurface(WGPUDevice device, const ExternalImageDescriptorIOSurface* cDescriptor) {
- Device* backendDevice = ToBackend(FromAPI(device));
- std::vector<MTLSharedEventAndSignalValue> waitEvents;
- for (const auto& waitEvent : cDescriptor->waitEvents) {
- waitEvents.push_back(
- {static_cast<id<MTLSharedEvent>>(waitEvent.sharedEvent), waitEvent.signaledValue});
- }
- auto deviceLock(backendDevice->GetScopedLock());
- Ref<TextureBase> texture = backendDevice->CreateTextureWrappingIOSurface(
- cDescriptor, cDescriptor->ioSurface, std::move(waitEvents));
- return ToAPI(texture.Detach());
-}
-
void IOSurfaceEndAccess(WGPUTexture cTexture,
ExternalImageIOSurfaceEndAccessDescriptor* descriptor) {
Texture* texture = ToBackend(FromAPI(cTexture));
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn
index d89df35..4f3b409 100644
--- a/src/dawn/tests/BUILD.gn
+++ b/src/dawn/tests/BUILD.gn
@@ -643,10 +643,7 @@
if (is_mac || is_ios) {
if (dawn_enable_metal) {
- sources += [
- "end2end/IOSurfaceWrappingTests.cpp",
- "end2end/VideoViewsTests_mac.cpp",
- ]
+ sources += [ "end2end/VideoViewsTests_mac.cpp" ]
}
sources += [ "end2end/BufferHostMappedPointerTests_apple.mm" ]
diff --git a/src/dawn/tests/end2end/IOSurfaceWrappingTests.cpp b/src/dawn/tests/end2end/IOSurfaceWrappingTests.cpp
deleted file mode 100644
index fb0fb0b..0000000
--- a/src/dawn/tests/end2end/IOSurfaceWrappingTests.cpp
+++ /dev/null
@@ -1,700 +0,0 @@
-// Copyright 2019 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreVideo/CVPixelBuffer.h>
-#include <IOSurface/IOSurface.h>
-
-#include <memory>
-#include <thread>
-#include <vector>
-
-#include "dawn/tests/DawnTest.h"
-
-#include "dawn/native/MetalBackend.h"
-#include "dawn/utils/ComboRenderPipelineDescriptor.h"
-#include "dawn/utils/WGPUHelpers.h"
-
-namespace dawn {
-namespace {
-
-void AddIntegerValue(CFMutableDictionaryRef dictionary, const CFStringRef key, int32_t value) {
- CFNumberRef number = CFNumberCreate(nullptr, kCFNumberSInt32Type, &value);
- CFDictionaryAddValue(dictionary, key, number);
- CFRelease(number);
-}
-
-class ScopedIOSurfaceRef {
- public:
- ScopedIOSurfaceRef() : mSurface(nullptr) {}
- explicit ScopedIOSurfaceRef(IOSurfaceRef surface) : mSurface(surface) {}
-
- ~ScopedIOSurfaceRef() {
- if (mSurface != nullptr) {
- CFRelease(mSurface);
- mSurface = nullptr;
- }
- }
-
- IOSurfaceRef get() const { return mSurface; }
-
- ScopedIOSurfaceRef(ScopedIOSurfaceRef&& other) {
- if (mSurface != nullptr) {
- CFRelease(mSurface);
- }
- mSurface = other.mSurface;
- other.mSurface = nullptr;
- }
-
- ScopedIOSurfaceRef& operator=(ScopedIOSurfaceRef&& other) {
- if (mSurface != nullptr) {
- CFRelease(mSurface);
- }
- mSurface = other.mSurface;
- other.mSurface = nullptr;
-
- return *this;
- }
-
- ScopedIOSurfaceRef(const ScopedIOSurfaceRef&) = delete;
- ScopedIOSurfaceRef& operator=(const ScopedIOSurfaceRef&) = delete;
-
- private:
- IOSurfaceRef mSurface = nullptr;
-};
-
-ScopedIOSurfaceRef CreateSinglePlaneIOSurface(uint32_t width,
- uint32_t height,
- uint32_t format,
- uint32_t bytesPerElement) {
- CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
- kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- AddIntegerValue(dict, kIOSurfaceWidth, width);
- AddIntegerValue(dict, kIOSurfaceHeight, height);
- AddIntegerValue(dict, kIOSurfacePixelFormat, format);
- AddIntegerValue(dict, kIOSurfaceBytesPerElement, bytesPerElement);
-
- IOSurfaceRef ioSurface = IOSurfaceCreate(dict);
- EXPECT_NE(nullptr, ioSurface);
- CFRelease(dict);
-
- return ScopedIOSurfaceRef(ioSurface);
-}
-
-class IOSurfaceTestBase : public DawnTest {
- public:
- wgpu::Texture WrapIOSurface(const wgpu::TextureDescriptor* descriptor,
- IOSurfaceRef ioSurface,
- bool isInitialized = true) {
- native::metal::ExternalImageDescriptorIOSurface externDesc;
- externDesc.cTextureDescriptor = reinterpret_cast<const WGPUTextureDescriptor*>(descriptor);
- externDesc.ioSurface = ioSurface;
- externDesc.isInitialized = isInitialized;
- WGPUTexture texture = native::metal::WrapIOSurface(device.Get(), &externDesc);
- return wgpu::Texture::Acquire(texture);
- }
-};
-
-// A small fixture used to initialize default data for the IOSurface validation tests.
-// These tests are skipped if the harness is using the wire.
-class IOSurfaceValidationTests : public IOSurfaceTestBase {
- public:
- IOSurfaceValidationTests() {
- defaultIOSurface = CreateSinglePlaneIOSurface(10, 10, kCVPixelFormatType_32BGRA, 4);
-
- descriptor.dimension = wgpu::TextureDimension::e2D;
- descriptor.format = wgpu::TextureFormat::BGRA8Unorm;
- descriptor.size = {10, 10, 1};
- descriptor.sampleCount = 1;
- descriptor.mipLevelCount = 1;
- descriptor.usage = wgpu::TextureUsage::RenderAttachment;
- }
-
- protected:
- wgpu::TextureDescriptor descriptor;
- ScopedIOSurfaceRef defaultIOSurface;
-};
-
-// Test a successful wrapping of an IOSurface in a texture
-TEST_P(IOSurfaceValidationTests, Success) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get());
- ASSERT_NE(texture.Get(), nullptr);
-}
-
-// Test an error occurs if the texture descriptor is invalid
-TEST_P(IOSurfaceValidationTests, InvalidTextureDescriptor) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
-
- wgpu::ChainedStruct chainedDescriptor;
- descriptor.nextInChain = &chainedDescriptor;
-
- ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
- ASSERT_EQ(texture.Get(), nullptr);
-}
-
-// Test an error occurs if the descriptor dimension isn't 2D
-// TODO(crbug.com/dawn/814): Test 1D textures when implemented
-TEST_P(IOSurfaceValidationTests, InvalidTextureDimension) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- descriptor.dimension = wgpu::TextureDimension::e3D;
-
- ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
- ASSERT_EQ(texture.Get(), nullptr);
-}
-
-// Test an error occurs if the descriptor mip level count isn't 1
-TEST_P(IOSurfaceValidationTests, InvalidMipLevelCount) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- descriptor.mipLevelCount = 2;
-
- ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
- ASSERT_EQ(texture.Get(), nullptr);
-}
-
-// Test an error occurs if the descriptor depth isn't 1
-TEST_P(IOSurfaceValidationTests, InvalidDepth) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- descriptor.size.depthOrArrayLayers = 2;
-
- ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
- ASSERT_EQ(texture.Get(), nullptr);
-}
-
-// Test an error occurs if the descriptor sample count isn't 1
-TEST_P(IOSurfaceValidationTests, InvalidSampleCount) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- descriptor.sampleCount = 4;
-
- ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
- ASSERT_EQ(texture.Get(), nullptr);
-}
-
-// Test an error occurs if the descriptor width doesn't match the surface's
-TEST_P(IOSurfaceValidationTests, InvalidWidth) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- descriptor.size.width = 11;
-
- ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
- ASSERT_EQ(texture.Get(), nullptr);
-}
-
-// Test an error occurs if the descriptor height doesn't match the surface's
-TEST_P(IOSurfaceValidationTests, InvalidHeight) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- descriptor.size.height = 11;
-
- ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
- ASSERT_EQ(texture.Get(), nullptr);
-}
-
-// Test an error occurs if the descriptor format isn't compatible with the IOSurface's
-TEST_P(IOSurfaceValidationTests, InvalidFormat) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- descriptor.format = wgpu::TextureFormat::R8Unorm;
-
- ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
- ASSERT_EQ(texture.Get(), nullptr);
-}
-
-class IOSurfaceTransientAttachmentValidationTests : public IOSurfaceValidationTests {
- void SetUp() override {
- IOSurfaceValidationTests::SetUp();
-
- // Skip all tests if the transient attachments feature is not supported.
- DAWN_TEST_UNSUPPORTED_IF(!SupportsFeatures({wgpu::FeatureName::TransientAttachments}));
- }
-
- std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
- std::vector<wgpu::FeatureName> requiredFeatures = {};
- if (SupportsFeatures({wgpu::FeatureName::TransientAttachments})) {
- requiredFeatures.push_back(wgpu::FeatureName::TransientAttachments);
- }
- return requiredFeatures;
- }
-};
-
-// Test that an error occurs if the transient attachment is specified.
-TEST_P(IOSurfaceTransientAttachmentValidationTests, ErrorWhenSpecified) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
-
- descriptor.usage |= wgpu::TextureUsage::TransientAttachment;
-
- ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
- ASSERT_EQ(texture.Get(), nullptr);
-}
-
-// Fixture to test using IOSurfaces through different usages.
-// These tests are skipped if the harness is using the wire.
-class IOSurfaceUsageTests : public IOSurfaceTestBase {
- public:
- // Test that sampling a 1x1 works.
- void DoSampleTest(IOSurfaceRef ioSurface,
- wgpu::TextureFormat format,
- void* data,
- size_t dataSize,
- utils::RGBA8 expectedColor) {
- // Write the data to the IOSurface
- IOSurfaceLock(ioSurface, 0, nullptr);
- memcpy(IOSurfaceGetBaseAddress(ioSurface), data, dataSize);
- IOSurfaceUnlock(ioSurface, 0, nullptr);
-
- // The simplest texture sampling pipeline.
- wgpu::RenderPipeline pipeline;
- {
- wgpu::ShaderModule vs = utils::CreateShaderModule(device, R"(
- struct VertexOut {
- @location(0) texCoord : vec2f,
- @builtin(position) position : vec4f,
- }
-
- @vertex
- fn main(@builtin(vertex_index) VertexIndex : u32) -> VertexOut {
- var pos = array(
- vec2f(-2.0, -2.0),
- vec2f(-2.0, 2.0),
- vec2f( 2.0, -2.0),
- vec2f(-2.0, 2.0),
- vec2f( 2.0, -2.0),
- vec2f( 2.0, 2.0));
-
- var texCoord = array(
- vec2f(0.0, 0.0),
- vec2f(0.0, 1.0),
- vec2f(1.0, 0.0),
- vec2f(0.0, 1.0),
- vec2f(1.0, 0.0),
- vec2f(1.0, 1.0));
-
- var output : VertexOut;
- output.position = vec4f(pos[VertexIndex], 0.0, 1.0);
- output.texCoord = texCoord[VertexIndex];
- return output;
- }
- )");
- wgpu::ShaderModule fs = utils::CreateShaderModule(device, R"(
- @group(0) @binding(0) var sampler0 : sampler;
- @group(0) @binding(1) var texture0 : texture_2d<f32>;
-
- @fragment
- fn main(@location(0) texCoord : vec2f) -> @location(0) vec4f {
- return textureSample(texture0, sampler0, texCoord);
- }
- )");
-
- utils::ComboRenderPipelineDescriptor descriptor;
- descriptor.vertex.module = vs;
- descriptor.cFragment.module = fs;
- descriptor.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
-
- pipeline = device.CreateRenderPipeline(&descriptor);
- }
-
- // The bindgroup containing the texture view for the ioSurface as well as the sampler.
- wgpu::BindGroup bindGroup;
- {
- wgpu::TextureDescriptor textureDescriptor;
- textureDescriptor.dimension = wgpu::TextureDimension::e2D;
- textureDescriptor.format = format;
- textureDescriptor.size = {1, 1, 1};
- textureDescriptor.sampleCount = 1;
- textureDescriptor.mipLevelCount = 1;
- textureDescriptor.usage = wgpu::TextureUsage::TextureBinding;
- wgpu::Texture wrappingTexture = WrapIOSurface(&textureDescriptor, ioSurface);
-
- wgpu::TextureView textureView = wrappingTexture.CreateView();
-
- wgpu::Sampler sampler = device.CreateSampler();
-
- bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
- {{0, sampler}, {1, textureView}});
- }
-
- // Submit commands samping from the ioSurface and writing the result to renderPass.color
- utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- {
- wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
- pass.SetPipeline(pipeline);
- pass.SetBindGroup(0, bindGroup);
- pass.Draw(6);
- pass.End();
- }
-
- wgpu::CommandBuffer commands = encoder.Finish();
- queue.Submit(1, &commands);
-
- EXPECT_PIXEL_RGBA8_EQ(expectedColor, renderPass.color, 0, 0);
- }
-
- // Test that clearing using BeginRenderPass writes correct data in the ioSurface.
- void DoClearTest(IOSurfaceRef ioSurface,
- wgpu::TextureFormat format,
- void* data,
- size_t dataSize) {
- // Get a texture view for the ioSurface
- wgpu::TextureDescriptor textureDescriptor;
- textureDescriptor.dimension = wgpu::TextureDimension::e2D;
- textureDescriptor.format = format;
- textureDescriptor.size = {1, 1, 1};
- textureDescriptor.sampleCount = 1;
- textureDescriptor.mipLevelCount = 1;
- textureDescriptor.usage = wgpu::TextureUsage::RenderAttachment;
- wgpu::Texture ioSurfaceTexture = WrapIOSurface(&textureDescriptor, ioSurface);
-
- wgpu::TextureView ioSurfaceView = ioSurfaceTexture.CreateView();
-
- utils::ComboRenderPassDescriptor renderPassDescriptor({ioSurfaceView}, {});
- renderPassDescriptor.cColorAttachments[0].clearValue = {1 / 255.0f, 2 / 255.0f, 3 / 255.0f,
- 4 / 255.0f};
-
- // Execute commands to clear the ioSurface
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPassDescriptor);
- pass.End();
-
- wgpu::CommandBuffer commands = encoder.Finish();
- queue.Submit(1, &commands);
-
- // Wait for the commands touching the IOSurface to be scheduled
- native::metal::WaitForCommandsToBeScheduled(device.Get());
-
- // Check the correct data was written
- IOSurfaceLock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
- ASSERT_EQ(0, memcmp(IOSurfaceGetBaseAddress(ioSurface), data, dataSize));
- IOSurfaceUnlock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
- }
-};
-
-// Test sampling from a R8 IOSurface
-TEST_P(IOSurfaceUsageTests, SampleFromR8IOSurface) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- ScopedIOSurfaceRef ioSurface =
- CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_OneComponent8, 1);
-
- uint8_t data = 0x01;
- DoSampleTest(ioSurface.get(), wgpu::TextureFormat::R8Unorm, &data, sizeof(data),
- utils::RGBA8(1, 0, 0, 255));
-}
-
-// Test clearing a R8 IOSurface
-TEST_P(IOSurfaceUsageTests, ClearR8IOSurface) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- ScopedIOSurfaceRef ioSurface =
- CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_OneComponent8, 1);
-
- uint8_t data = 0x01;
- DoClearTest(ioSurface.get(), wgpu::TextureFormat::R8Unorm, &data, sizeof(data));
-}
-
-// Test sampling from a RG8 IOSurface
-TEST_P(IOSurfaceUsageTests, SampleFromRG8IOSurface) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- ScopedIOSurfaceRef ioSurface =
- CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_TwoComponent8, 2);
-
- uint16_t data = 0x0102; // Stored as (G, R)
- DoSampleTest(ioSurface.get(), wgpu::TextureFormat::RG8Unorm, &data, sizeof(data),
- utils::RGBA8(2, 1, 0, 255));
-}
-
-// Test clearing a RG8 IOSurface
-TEST_P(IOSurfaceUsageTests, ClearRG8IOSurface) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- ScopedIOSurfaceRef ioSurface =
- CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_TwoComponent8, 2);
-
- uint16_t data = 0x0201;
- DoClearTest(ioSurface.get(), wgpu::TextureFormat::RG8Unorm, &data, sizeof(data));
-}
-
-// Test sampling from a BGRA8 IOSurface
-TEST_P(IOSurfaceUsageTests, SampleFromBGRA8IOSurface) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32BGRA, 4);
-
- uint32_t data = 0x01020304; // Stored as (A, R, G, B)
- DoSampleTest(ioSurface.get(), wgpu::TextureFormat::BGRA8Unorm, &data, sizeof(data),
- utils::RGBA8(2, 3, 4, 1));
-}
-
-// Test clearing a BGRA8 IOSurface
-TEST_P(IOSurfaceUsageTests, ClearBGRA8IOSurface) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32BGRA, 4);
-
- uint32_t data = 0x04010203;
- DoClearTest(ioSurface.get(), wgpu::TextureFormat::BGRA8Unorm, &data, sizeof(data));
-}
-
-// Test sampling from an RGBA8 IOSurface
-TEST_P(IOSurfaceUsageTests, SampleFromRGBA8IOSurface) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32RGBA, 4);
-
- uint32_t data = 0x01020304; // Stored as (A, B, G, R)
- DoSampleTest(ioSurface.get(), wgpu::TextureFormat::RGBA8Unorm, &data, sizeof(data),
- utils::RGBA8(4, 3, 2, 1));
-}
-
-// Test clearing an RGBA8 IOSurface
-TEST_P(IOSurfaceUsageTests, ClearRGBA8IOSurface) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32RGBA, 4);
-
- uint32_t data = 0x04030201;
- DoClearTest(ioSurface.get(), wgpu::TextureFormat::RGBA8Unorm, &data, sizeof(data));
-}
-
-// Test that texture with color is cleared when isInitialized = false
-TEST_P(IOSurfaceUsageTests, UninitializedTextureIsCleared) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
-
- ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32RGBA, 4);
- uint32_t data = 0x04030201;
-
- IOSurfaceLock(ioSurface.get(), 0, nullptr);
- memcpy(IOSurfaceGetBaseAddress(ioSurface.get()), &data, sizeof(data));
- IOSurfaceUnlock(ioSurface.get(), 0, nullptr);
-
- wgpu::TextureDescriptor textureDescriptor;
- textureDescriptor.dimension = wgpu::TextureDimension::e2D;
- textureDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
- textureDescriptor.size = {1, 1, 1};
- textureDescriptor.sampleCount = 1;
- textureDescriptor.mipLevelCount = 1;
- textureDescriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
-
- // wrap ioSurface and ensure color is not visible when isInitialized set to false
- wgpu::Texture ioSurfaceTexture = WrapIOSurface(&textureDescriptor, ioSurface.get(), false);
- EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8(0, 0, 0, 0), ioSurfaceTexture, 0, 0);
-
- native::metal::ExternalImageIOSurfaceEndAccessDescriptor endAccessDesc;
- native::metal::IOSurfaceEndAccess(ioSurfaceTexture.Get(), &endAccessDesc);
- EXPECT_TRUE(endAccessDesc.isInitialized);
-}
-
-// Test that exporting a texture wrapping an IOSurface sets the isInitialized bit to
-// false if the contents are discard.
-TEST_P(IOSurfaceUsageTests, UninitializedOnEndAccess) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
-
- ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32RGBA, 4);
- uint32_t data = 0x04030201;
-
- IOSurfaceLock(ioSurface.get(), 0, nullptr);
- memcpy(IOSurfaceGetBaseAddress(ioSurface.get()), &data, sizeof(data));
- IOSurfaceUnlock(ioSurface.get(), 0, nullptr);
-
- wgpu::TextureDescriptor textureDescriptor;
- textureDescriptor.dimension = wgpu::TextureDimension::e2D;
- textureDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
- textureDescriptor.size = {1, 1, 1};
- textureDescriptor.sampleCount = 1;
- textureDescriptor.mipLevelCount = 1;
- textureDescriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
-
- // Wrap ioSurface
- wgpu::Texture ioSurfaceTexture = WrapIOSurface(&textureDescriptor, ioSurface.get(), true);
-
- // Uninitialize the teuxture with a render pass.
- utils::ComboRenderPassDescriptor renderPassDescriptor({ioSurfaceTexture.CreateView()});
- renderPassDescriptor.cColorAttachments[0].storeOp = wgpu::StoreOp::Discard;
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- encoder.BeginRenderPass(&renderPassDescriptor).End();
- wgpu::CommandBuffer commandBuffer = encoder.Finish();
- queue.Submit(1, &commandBuffer);
-
- native::metal::ExternalImageIOSurfaceEndAccessDescriptor endAccessDesc;
- native::metal::IOSurfaceEndAccess(ioSurfaceTexture.Get(), &endAccessDesc);
- EXPECT_FALSE(endAccessDesc.isInitialized);
-}
-
-// Test that an IOSurface may be imported across multiple devices.
-TEST_P(IOSurfaceUsageTests, WriteThenConcurrentReadThenWrite) {
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
-
- ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32RGBA, 4);
- uint32_t data = 0x04030201;
-
- IOSurfaceLock(ioSurface.get(), 0, nullptr);
- memcpy(IOSurfaceGetBaseAddress(ioSurface.get()), &data, sizeof(data));
- IOSurfaceUnlock(ioSurface.get(), 0, nullptr);
-
- // Make additional devices. We will import with the writeDevice, then read it concurrently with
- // both readDevices.
- wgpu::Device writeDevice = device;
- wgpu::Device readDevice1 = CreateDevice();
- wgpu::Device readDevice2 = CreateDevice();
-
- wgpu::TextureDescriptor textureDesc;
- textureDesc.dimension = wgpu::TextureDimension::e2D;
- textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
- textureDesc.size = {1, 1, 1};
- textureDesc.sampleCount = 1;
- textureDesc.mipLevelCount = 1;
- textureDesc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
-
- // Wrap ioSurface
- native::metal::ExternalImageDescriptorIOSurface writeExternDesc;
- writeExternDesc.cTextureDescriptor =
- reinterpret_cast<const WGPUTextureDescriptor*>(&textureDesc);
- writeExternDesc.ioSurface = ioSurface.get();
- writeExternDesc.isInitialized = true;
-
- wgpu::Texture writeTexture =
- wgpu::Texture::Acquire(native::metal::WrapIOSurface(writeDevice.Get(), &writeExternDesc));
-
- // Clear the texture to green.
- {
- utils::ComboRenderPassDescriptor renderPassDescriptor({writeTexture.CreateView()});
- renderPassDescriptor.cColorAttachments[0].clearValue = {0.0, 1.0, 0.0, 1.0};
- wgpu::CommandEncoder encoder = writeDevice.CreateCommandEncoder();
- encoder.BeginRenderPass(&renderPassDescriptor).End();
- wgpu::CommandBuffer commandBuffer = encoder.Finish();
- writeDevice.GetQueue().Submit(1, &commandBuffer);
- }
-
- // End access.
- native::metal::ExternalImageIOSurfaceEndAccessDescriptor endWriteAccessDesc;
- native::metal::IOSurfaceEndAccess(writeTexture.Get(), &endWriteAccessDesc);
- EXPECT_TRUE(endWriteAccessDesc.isInitialized);
-
- native::metal::ExternalImageDescriptorIOSurface externDesc;
- externDesc.cTextureDescriptor = reinterpret_cast<const WGPUTextureDescriptor*>(&textureDesc);
- externDesc.ioSurface = ioSurface.get();
- externDesc.isInitialized = true;
- externDesc.waitEvents.push_back(
- {endWriteAccessDesc.sharedEvent, endWriteAccessDesc.signaledValue});
-
- // Wrap on two separate devices to read it.
- wgpu::Texture readTexture1 =
- wgpu::Texture::Acquire(native::metal::WrapIOSurface(readDevice1.Get(), &externDesc));
- wgpu::Texture readTexture2 =
- wgpu::Texture::Acquire(native::metal::WrapIOSurface(readDevice2.Get(), &externDesc));
-
- // Expect the texture to be green
- EXPECT_TEXTURE_EQ(readDevice1, utils::RGBA8(0, 255, 0, 255), readTexture1, {0, 0});
- EXPECT_TEXTURE_EQ(readDevice2, utils::RGBA8(0, 255, 0, 255), readTexture2, {0, 0});
-
- // End access on both read textures.
- native::metal::ExternalImageIOSurfaceEndAccessDescriptor endReadAccessDesc1;
- native::metal::IOSurfaceEndAccess(readTexture1.Get(), &endReadAccessDesc1);
- EXPECT_TRUE(endReadAccessDesc1.isInitialized);
-
- native::metal::ExternalImageIOSurfaceEndAccessDescriptor endReadAccessDesc2;
- native::metal::IOSurfaceEndAccess(readTexture2.Get(), &endReadAccessDesc2);
- EXPECT_TRUE(endReadAccessDesc2.isInitialized);
-
- // Import again for writing. It should not race with the previous reads.
- writeExternDesc.waitEvents = {endReadAccessDesc1, endReadAccessDesc2};
- writeExternDesc.isInitialized = true;
- writeTexture =
- wgpu::Texture::Acquire(native::metal::WrapIOSurface(writeDevice.Get(), &writeExternDesc));
-
- // Clear the texture to blue.
- {
- utils::ComboRenderPassDescriptor renderPassDescriptor({writeTexture.CreateView()});
- renderPassDescriptor.cColorAttachments[0].clearValue = {0.0, 0.0, 1.0, 1.0};
- wgpu::CommandEncoder encoder = writeDevice.CreateCommandEncoder();
- encoder.BeginRenderPass(&renderPassDescriptor).End();
- wgpu::CommandBuffer commandBuffer = encoder.Finish();
- writeDevice.GetQueue().Submit(1, &commandBuffer);
- }
- // Finally, expect the contents to be blue now.
- EXPECT_TEXTURE_EQ(writeDevice, utils::RGBA8(0, 0, 255, 255), writeTexture, {0, 0});
- native::metal::IOSurfaceEndAccess(writeTexture.Get(), &endWriteAccessDesc);
- EXPECT_TRUE(endWriteAccessDesc.isInitialized);
-}
-
-class IOSurfaceMultithreadTests : public IOSurfaceUsageTests {
- protected:
- std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
- std::vector<wgpu::FeatureName> features;
- // TODO(crbug.com/dawn/1678): DawnWire doesn't support thread safe API yet.
- if (!UsesWire()) {
- features.push_back(wgpu::FeatureName::ImplicitDeviceSynchronization);
- }
- return features;
- }
-
- void SetUp() override {
- IOSurfaceUsageTests::SetUp();
- // TODO(crbug.com/dawn/1678): DawnWire doesn't support thread safe API yet.
- DAWN_TEST_UNSUPPORTED_IF(UsesWire());
- }
-};
-
-// Test that texture with color is cleared when isInitialized = false. There shoudn't be any data
-// race if multiple of them are created on multiple threads.
-TEST_P(IOSurfaceMultithreadTests, UninitializedTexturesAreCleared_OnMultipleThreads) {
- utils::RunInParallel(10, [this](uint32_t) {
- ScopedIOSurfaceRef ioSurface =
- CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32RGBA, 4);
- uint32_t data = 0x04030201;
-
- IOSurfaceLock(ioSurface.get(), 0, nullptr);
- memcpy(IOSurfaceGetBaseAddress(ioSurface.get()), &data, sizeof(data));
- IOSurfaceUnlock(ioSurface.get(), 0, nullptr);
-
- wgpu::TextureDescriptor textureDescriptor;
- textureDescriptor.dimension = wgpu::TextureDimension::e2D;
- textureDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
- textureDescriptor.size = {1, 1, 1};
- textureDescriptor.sampleCount = 1;
- textureDescriptor.mipLevelCount = 1;
- textureDescriptor.usage =
- wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
-
- // wrap ioSurface and ensure color is not visible when isInitialized set to false
- wgpu::Texture ioSurfaceTexture = WrapIOSurface(&textureDescriptor, ioSurface.get(), false);
- EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8(0, 0, 0, 0), ioSurfaceTexture, 0, 0);
-
- native::metal::ExternalImageIOSurfaceEndAccessDescriptor endAccessDesc;
- native::metal::IOSurfaceEndAccess(ioSurfaceTexture.Get(), &endAccessDesc);
- EXPECT_TRUE(endAccessDesc.isInitialized);
- });
-}
-
-// Test that wrapping multiple IOSurface and clear them on multiple threads work.
-TEST_P(IOSurfaceMultithreadTests, WrapAndClear_OnMultipleThreads) {
- utils::RunInParallel(10, [this](uint32_t) {
- ScopedIOSurfaceRef ioSurface =
- CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32BGRA, 4);
-
- uint32_t data = 0x04010203;
- DoClearTest(ioSurface.get(), wgpu::TextureFormat::BGRA8Unorm, &data, sizeof(data));
- });
-}
-
-DAWN_INSTANTIATE_TEST(IOSurfaceValidationTests, MetalBackend());
-DAWN_INSTANTIATE_TEST(IOSurfaceTransientAttachmentValidationTests, MetalBackend());
-DAWN_INSTANTIATE_TEST(IOSurfaceUsageTests, MetalBackend());
-DAWN_INSTANTIATE_TEST(IOSurfaceMultithreadTests, MetalBackend());
-
-} // anonymous namespace
-} // namespace dawn