#if MLN_RENDER_BACKEND_METAL #include #include #include #include #include #include #include #include #include using namespace mln; namespace { class TestMetalBackend final : public mtl::RendererBackend { public: TestMetalBackend() : RendererBackend(gfx::ContextMode::Unique) {} gfx::Renderable& getDefaultRenderable() override { std::abort(); } void updateAssumedState() override {} private: void activate() override {} void deactivate() override {} }; } // namespace TEST(MetalRetainedAttachments, ClearActionsApplyToCombinedDepthStencil) { auto pool = NS::TransferPtr(NS::AutoreleasePool::alloc()->init()); auto device = NS::TransferPtr(MTL::CreateSystemDefaultDevice()); if (!device) GTEST_SKIP() << "Metal device unavailable"; auto colorDescriptor = MTL::TextureDescriptor::texture2DDescriptor(MTL::PixelFormatRGBA8Unorm, 4, 4, false); auto combinedDescriptor = MTL::TextureDescriptor::texture2DDescriptor(MTL::PixelFormatDepth32Float_Stencil8, 4, 4, false); colorDescriptor->setUsage(MTL::TextureUsageRenderTarget); combinedDescriptor->setUsage(MTL::TextureUsageRenderTarget); auto colorTexture = NS::TransferPtr(device->newTexture(colorDescriptor)); auto combinedTexture = NS::TransferPtr(device->newTexture(combinedDescriptor)); if (!combinedTexture) GTEST_SKIP() << "Combined depth-stencil texture unavailable"; ASSERT_TRUE(colorTexture); auto descriptor = NS::TransferPtr(MTL::RenderPassDescriptor::alloc()->init()); descriptor->colorAttachments()->object(0)->setTexture(colorTexture.get()); descriptor->depthAttachment()->setTexture(combinedTexture.get()); descriptor->stencilAttachment()->setTexture(combinedTexture.get()); const auto applied = mtl::detail::applyRenderPassClears( *descriptor.get(), Color{0.2f, 0.3f, 0.4f, 0.5f}, 1.0f, 0); EXPECT_TRUE(applied.color); EXPECT_TRUE(applied.depth); EXPECT_TRUE(applied.stencil); EXPECT_EQ(descriptor->colorAttachments()->object(0)->loadAction(), MTL::LoadActionClear); EXPECT_EQ(descriptor->depthAttachment()->loadAction(), MTL::LoadActionClear); EXPECT_EQ(descriptor->stencilAttachment()->loadAction(), MTL::LoadActionClear); EXPECT_EQ(descriptor->colorAttachments()->object(0)->storeAction(), MTL::StoreActionStore); EXPECT_EQ(descriptor->depthAttachment()->storeAction(), MTL::StoreActionStore); EXPECT_EQ(descriptor->stencilAttachment()->storeAction(), MTL::StoreActionStore); EXPECT_DOUBLE_EQ(descriptor->depthAttachment()->clearDepth(), 1.0); EXPECT_EQ(descriptor->stencilAttachment()->clearStencil(), 0u); EXPECT_EQ(descriptor->depthAttachment()->texture(), descriptor->stencilAttachment()->texture()); } TEST(MetalRetainedAttachments, OffscreenBindsRequestedAttachmentsAndSkipsAbsentOnes) { auto pool = NS::TransferPtr(NS::AutoreleasePool::alloc()->init()); auto device = NS::TransferPtr(MTL::CreateSystemDefaultDevice()); if (!device) GTEST_SKIP() << "Metal device unavailable"; TestMetalBackend backend; mtl::Context context{backend}; mtl::OffscreenTexture retained(context, {4, 4}, gfx::TextureChannelDataType::UnsignedByte, true, true); ASSERT_TRUE(retained.isRenderable()); auto& retainedResource = retained.getResource(); retainedResource.bind(); const auto& retainedDescriptor = retainedResource.getRenderPassDescriptor(); ASSERT_TRUE(retainedDescriptor); ASSERT_NE(retainedDescriptor->colorAttachments()->object(0)->texture(), nullptr); ASSERT_NE(retainedDescriptor->depthAttachment()->texture(), nullptr); ASSERT_NE(retainedDescriptor->stencilAttachment()->texture(), nullptr); #if TARGET_OS_SIMULATOR || defined(__x86_64__) EXPECT_EQ(retainedDescriptor->depthAttachment()->texture(), retainedDescriptor->stencilAttachment()->texture()); #else EXPECT_NE(retainedDescriptor->depthAttachment()->texture(), retainedDescriptor->stencilAttachment()->texture()); #endif mtl::OffscreenTexture colorOnly(context, {4, 4}, gfx::TextureChannelDataType::UnsignedByte, false, false); ASSERT_TRUE(colorOnly.isRenderable()); auto& colorResource = colorOnly.getResource(); colorResource.bind(); const auto& colorDescriptor = colorResource.getRenderPassDescriptor(); ASSERT_TRUE(colorDescriptor); EXPECT_EQ(colorDescriptor->depthAttachment()->texture(), nullptr); EXPECT_EQ(colorDescriptor->stencilAttachment()->texture(), nullptr); const auto applied = mtl::detail::applyRenderPassClears(*colorDescriptor.get(), std::nullopt, 1.0f, 0); EXPECT_FALSE(applied.depth); EXPECT_FALSE(applied.stencil); } #endif // MLN_RENDER_BACKEND_METAL