Exemple #1
0
        /// <summary>
        /// Render an image from the given cameras and compare it to the reference image.
        /// </summary>
        /// <param name="expected">The expected image that should be rendered by the camera.</param>
        /// <param name="cameras">The cameras to render from.</param>
        /// <param name="settings">Optional settings that control how the image comparison is performed. Can be null, in which case the rendered image is required to be exactly identical to the reference.</param>
        public static void AreEqual(Texture2D expected, IEnumerable <Camera> cameras, ImageComparisonSettings settings = null)
        {
            if (cameras == null)
            {
                throw new ArgumentNullException(nameof(cameras));
            }

            if (settings == null)
            {
                settings = new ImageComparisonSettings();
            }

            int width  = settings.TargetWidth;
            int height = settings.TargetHeight;
            var format = expected != null ? expected.format : TextureFormat.ARGB32;

            // Some HDRP test fail with HDRP batcher because shaders variant are compiled "on the fly" in editor mode.
            // Persistent PerMaterial CBUFFER is build during culling, but some nodes could use new variants and CBUFFER will be up to date next frame.
            // ( this is editor specific, standalone player has no frame delay issue because all variants are ready at init stage )
            // This PR adds a dummy rendered frame before doing the real rendering and compare images ( test already has frame delay, but there is no rendering )
            int dummyRenderedFrameCount = 1;

            var       rt     = RenderTexture.GetTemporary(width, height, 24);
            Texture2D actual = null;

            try
            {
                for (int i = 0; i < dummyRenderedFrameCount + 1; i++)        // x frame delay + the last one is the one really tested ( ie 5 frames delay means 6 frames are rendered )
                {
                    foreach (var camera in cameras)
                    {
                        camera.targetTexture = rt;
                        camera.Render();
                        camera.targetTexture = null;
                    }

                    // only proceed the test on the last renderered frame
                    if (dummyRenderedFrameCount == i)
                    {
                        actual = new Texture2D(width, height, format, false);
                        RenderTexture.active = rt;
                        actual.ReadPixels(new Rect(0, 0, width, height), 0, 0);
                        RenderTexture.active = null;

                        actual.Apply();

                        AreEqual(expected, actual, settings);
                    }
                }
            }
            finally
            {
                RenderTexture.ReleaseTemporary(rt);
                if (actual != null)
                {
                    UnityEngine.Object.Destroy(actual);
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Render an image from the given camera and compare it to the reference image.
        /// </summary>
        /// <param name="expected">The expected image that should be rendered by the camera.</param>
        /// <param name="camera">The camera to render from.</param>
        /// <param name="settings">Optional settings that control how the image comparison is performed. Can be null, in which case the rendered image is required to be exactly identical to the reference.</param>
        public static void AreEqual(Texture2D expected, Camera camera, ImageComparisonSettings settings = null)
        {
            if (camera == null)
            {
                throw new ArgumentNullException(nameof(camera));
            }

            AreEqual(expected, new List <Camera> {
                camera
            }, settings);
        }
Exemple #3
0
        /// <summary>
        /// Render an image from the given camera and check if it allocated memory while doing so.
        /// </summary>
        /// <param name="camera">The camera to render from.</param>
        /// <param name="width"> width of the image to be rendered</param>
        /// <param name="height"> height of the image to be rendered</param>
        public static void AllocatesMemory(Camera camera, ImageComparisonSettings settings = null, int gcAllocThreshold = 2)
        {
            if (camera == null)
            {
                throw new ArgumentNullException(nameof(camera));
            }

            if (settings == null)
            {
                settings = new ImageComparisonSettings();
            }

            int width  = settings.TargetWidth;
            int height = settings.TargetHeight;

            var defaultFormat            = (settings.UseHDR) ? SystemInfo.GetGraphicsFormat(DefaultFormat.HDR) : SystemInfo.GetGraphicsFormat(DefaultFormat.LDR);
            RenderTextureDescriptor desc = new RenderTextureDescriptor(width, height, defaultFormat, 24);

            var rt = RenderTexture.GetTemporary(desc);

            try
            {
                camera.targetTexture = rt;

                // Render the first frame at this resolution (Alloc are allowed here)
                camera.Render();

                var gcAllocRecorder = Recorder.Get("GC.Alloc");
                gcAllocRecorder.FilterToCurrentThread();

                Profiler.BeginSample("GraphicTests_GC_Alloc_Check");
                {
                    gcAllocRecorder.enabled = true;
                    camera.Render();
                    gcAllocRecorder.enabled = false;
                }
                Profiler.EndSample();

                // There are 2 GC.Alloc overhead for calling Camera.CustomRender
                int allocationCountOfRenderPipeline = gcAllocRecorder.sampleBlockCount - gcAllocThreshold;

                if (allocationCountOfRenderPipeline > 0)
                {
                    throw new Exception($"Memory allocation test failed, {allocationCountOfRenderPipeline} allocations detected. Look for GraphicTests_GC_Alloc_Check in the profiler for more details");
                }

                camera.targetTexture = null;
            }
            finally
            {
                RenderTexture.ReleaseTemporary(rt);
            }
        }
        /// <summary>
        /// Render an image from the given cameras and compare it to the reference image.
        /// </summary>
        /// <param name="expected">The expected image that should be rendered by the camera.</param>
        /// <param name="cameras">The cameras to render from.</param>
        /// <param name="settings">Optional settings that control how the image comparison is performed. Can be null, in which case the rendered image is required to be exactly identical to the reference.</param>
        public static void AreEqual(Texture2D expected, IEnumerable <Camera> cameras, ImageComparisonSettings settings = null)
        {
            if (cameras == null)
            {
                throw new ArgumentNullException(nameof(cameras));
            }

            if (settings == null)
            {
                settings = new ImageComparisonSettings();
            }

            int width  = settings.TargetWidth;
            int height = settings.TargetHeight;
            var format = expected != null ? expected.format : TextureFormat.ARGB32;

            var       rt     = RenderTexture.GetTemporary(width, height, 24);
            Texture2D actual = null;

            try
            {
                foreach (var camera in cameras)
                {
                    camera.targetTexture = rt;
                    camera.Render();
                    camera.targetTexture = null;
                }

                actual = new Texture2D(width, height, format, false);
                RenderTexture.active = rt;
                actual.ReadPixels(new Rect(0, 0, width, height), 0, 0);
                RenderTexture.active = null;

                actual.Apply();

                AreEqual(expected, actual, settings);
            }
            finally
            {
                RenderTexture.ReleaseTemporary(rt);
                if (actual != null)
                {
                    UnityEngine.Object.Destroy(actual);
                }
            }
        }
        /// <summary>
        /// Compares an image to a 'reference' image to see if it looks correct.
        /// </summary>
        /// <param name="expected">What the image is supposed to look like.</param>
        /// <param name="actual">What the image actually looks like.</param>
        /// <param name="settings">Optional settings that control how the comparison is performed. Can be null, in which case the images are required to be exactly identical.</param>
        public static void AreEqual(Texture2D expected, Texture2D actual, ImageComparisonSettings settings = null)
        {
            if (actual == null)
            {
                throw new ArgumentNullException("actual");
            }

            try
            {
                Assert.That(expected, Is.Not.Null, "No reference image was provided.");

                Assert.That(actual.width, Is.EqualTo(expected.width),
                            "The expected image had width {0}px, but the actual image had width {1}px.", expected.width,
                            actual.width);
                Assert.That(actual.height, Is.EqualTo(expected.height),
                            "The expected image had height {0}px, but the actual image had height {1}px.", expected.height,
                            actual.height);

                Assert.That(actual.format, Is.EqualTo(expected.format),
                            "The expected image had format {0} but the actual image had format {1}.", expected.format,
                            actual.format);

                using (var expectedPixels = new NativeArray <Color32>(expected.GetPixels32(0), Allocator.TempJob))
                    using (var actualPixels = new NativeArray <Color32>(actual.GetPixels32(0), Allocator.TempJob))
                        using (var diffPixels = new NativeArray <Color32>(expectedPixels.Length, Allocator.TempJob))
                            using (var sumOverThreshold = new NativeArray <float>(Mathf.CeilToInt(expectedPixels.Length / (float)k_BatchSize), Allocator.TempJob))
                            {
                                if (settings == null)
                                {
                                    settings = new ImageComparisonSettings();
                                }

                                new ComputeDiffJob
                                {
                                    expected         = expectedPixels,
                                    actual           = actualPixels,
                                    diff             = diffPixels,
                                    sumOverThreshold = sumOverThreshold,
                                    pixelThreshold   = settings.PerPixelCorrectnessThreshold
                                }.Schedule(expectedPixels.Length, k_BatchSize).Complete();

                                float averageDeltaE = sumOverThreshold.Sum() / (expected.width * expected.height);

                                try
                                {
                                    Assert.That(averageDeltaE, Is.LessThanOrEqualTo(settings.AverageCorrectnessThreshold));
                                }
                                catch (AssertionException)
                                {
                                    var diffImage       = new Texture2D(expected.width, expected.height, TextureFormat.RGB24, false);
                                    var diffPixelsArray = new Color32[expected.width * expected.height];
                                    diffPixels.CopyTo(diffPixelsArray);
                                    diffImage.SetPixels32(diffPixelsArray, 0);
                                    diffImage.Apply(false);

                                    TestContext.CurrentContext.Test.Properties.Set("DiffImage", Convert.ToBase64String(diffImage.EncodeToPNG()));
                                    throw;
                                }
                            }
            }
            catch (AssertionException)
            {
                TestContext.CurrentContext.Test.Properties.Set("Image", Convert.ToBase64String(actual.EncodeToPNG()));
                throw;
            }
        }
Exemple #6
0
        /// <summary>
        /// Compares an image to a 'reference' image to see if it looks correct.
        /// </summary>
        /// <param name="expected">What the image is supposed to look like.</param>
        /// <param name="actual">What the image actually looks like.</param>
        /// <param name="settings">Optional settings that control how the comparison is performed. Can be null, in which case the images are required to be exactly identical.</param>
        public static void AreEqual(Texture2D expected, Texture2D actual, ImageComparisonSettings settings = null)
        {
            if (actual == null)
            {
                throw new ArgumentNullException("actual");
            }

#if UNITY_EDITOR
            var imagesWritten = new HashSet <string>();
            var dirName       = Path.Combine("Assets/ActualImages", string.Format("{0}/{1}/{2}", UseGraphicsTestCasesAttribute.ColorSpace, UseGraphicsTestCasesAttribute.Platform, UseGraphicsTestCasesAttribute.GraphicsDevice));
            Directory.CreateDirectory(dirName);
#endif

            try
            {
                Assert.That(expected, Is.Not.Null, "No reference image was provided.");

                Assert.That(actual.width, Is.EqualTo(expected.width),
                            "The expected image had width {0}px, but the actual image had width {1}px.", expected.width,
                            actual.width);
                Assert.That(actual.height, Is.EqualTo(expected.height),
                            "The expected image had height {0}px, but the actual image had height {1}px.", expected.height,
                            actual.height);

                Assert.That(actual.format, Is.EqualTo(expected.format),
                            "The expected image had format {0} but the actual image had format {1}.", expected.format,
                            actual.format);

                using (var expectedPixels = new NativeArray <Color32>(expected.GetPixels32(0), Allocator.TempJob))
                    using (var actualPixels = new NativeArray <Color32>(actual.GetPixels32(0), Allocator.TempJob))
                        using (var diffPixels = new NativeArray <Color32>(expectedPixels.Length, Allocator.TempJob))
                            using (var sumOverThreshold = new NativeArray <float>(Mathf.CeilToInt(expectedPixels.Length / (float)k_BatchSize), Allocator.TempJob))
                            {
                                if (settings == null)
                                {
                                    settings = new ImageComparisonSettings();
                                }

                                new ComputeDiffJob
                                {
                                    expected         = expectedPixels,
                                    actual           = actualPixels,
                                    diff             = diffPixels,
                                    sumOverThreshold = sumOverThreshold,
                                    pixelThreshold   = settings.PerPixelCorrectnessThreshold
                                }.Schedule(expectedPixels.Length, k_BatchSize).Complete();

                                float averageDeltaE = sumOverThreshold.Sum() / (expected.width * expected.height);

                                try
                                {
                                    Assert.That(averageDeltaE, Is.LessThanOrEqualTo(settings.AverageCorrectnessThreshold));
                                }
                                catch (AssertionException)
                                {
                                    var diffImage       = new Texture2D(expected.width, expected.height, TextureFormat.RGB24, false);
                                    var diffPixelsArray = new Color32[expected.width * expected.height];
                                    diffPixels.CopyTo(diffPixelsArray);
                                    diffImage.SetPixels32(diffPixelsArray, 0);
                                    diffImage.Apply(false);

#if UNITY_EDITOR
                                    if (sDontWriteToLog)
                                    {
                                        var bytes = diffImage.EncodeToPNG();
                                        var path  = Path.Combine(dirName, TestContext.CurrentContext.Test.Name + ".diff.png");
                                        File.WriteAllBytes(path, bytes);
                                        imagesWritten.Add(path);
                                    }
                                    else
#endif
                                    TestContext.CurrentContext.Test.Properties.Set("DiffImage", Convert.ToBase64String(diffImage.EncodeToPNG()));

                                    throw;
                                }
                            }
            }
            catch (AssertionException)
            {
#if UNITY_EDITOR
                if (sDontWriteToLog)
                {
                    var bytes = actual.EncodeToPNG();
                    var path  = Path.Combine(dirName, TestContext.CurrentContext.Test.Name + ".png");
                    File.WriteAllBytes(path, bytes);
                    imagesWritten.Add(path);

                    AssetDatabase.Refresh();

                    UnityEditor.TestTools.Graphics.Utils.SetupReferenceImageImportSettings(imagesWritten);
                }
                else
#endif
                TestContext.CurrentContext.Test.Properties.Set("Image", Convert.ToBase64String(actual.EncodeToPNG()));

                throw;
            }
        }
Exemple #7
0
        /// <summary>
        /// Compares an image to a 'reference' image to see if it looks correct.
        /// </summary>
        /// <param name="expected">What the image is supposed to look like.</param>
        /// <param name="actual">What the image actually looks like.</param>
        /// <param name="settings">Optional settings that control how the comparison is performed. Can be null, in which case the images are required to be exactly identical.</param>
        public static void AreEqual(Texture2D expected, Texture2D actual, ImageComparisonSettings settings = null)
        {
            if (actual == null)
            {
                throw new ArgumentNullException(nameof(actual));
            }

            var dirName            = Path.Combine("Assets/ActualImages", string.Format("{0}/{1}/{2}", UseGraphicsTestCasesAttribute.ColorSpace, UseGraphicsTestCasesAttribute.Platform, UseGraphicsTestCasesAttribute.GraphicsDevice));
            var failedImageMessage = new FailedImageMessage
            {
                PathName  = dirName,
                ImageName = TestContext.CurrentContext.Test.Name,
            };

            try
            {
                Assert.That(expected, Is.Not.Null, "No reference image was provided.");

                Assert.That(actual.width, Is.EqualTo(expected.width),
                            "The expected image had width {0}px, but the actual image had width {1}px.", expected.width,
                            actual.width);
                Assert.That(actual.height, Is.EqualTo(expected.height),
                            "The expected image had height {0}px, but the actual image had height {1}px.", expected.height,
                            actual.height);

                Assert.That(actual.format, Is.EqualTo(expected.format),
                            "The expected image had format {0} but the actual image had format {1}.", expected.format,
                            actual.format);

                using (var expectedPixels = new NativeArray <Color32>(expected.GetPixels32(0), Allocator.TempJob))
                    using (var actualPixels = new NativeArray <Color32>(actual.GetPixels32(0), Allocator.TempJob))
                        using (var diffPixels = new NativeArray <Color32>(expectedPixels.Length, Allocator.TempJob))
                            using (var sumOverThreshold = new NativeArray <float>(Mathf.CeilToInt(expectedPixels.Length / (float)k_BatchSize), Allocator.TempJob))
                            {
                                if (settings == null)
                                {
                                    settings = new ImageComparisonSettings();
                                }

                                new ComputeDiffJob
                                {
                                    expected         = expectedPixels,
                                    actual           = actualPixels,
                                    diff             = diffPixels,
                                    sumOverThreshold = sumOverThreshold,
                                    pixelThreshold   = settings.PerPixelCorrectnessThreshold
                                }.Schedule(expectedPixels.Length, k_BatchSize).Complete();

                                float averageDeltaE = sumOverThreshold.Sum() / (expected.width * expected.height);

                                try
                                {
                                    Assert.That(averageDeltaE, Is.LessThanOrEqualTo(settings.AverageCorrectnessThreshold));
                                }
                                catch (AssertionException)
                                {
                                    var diffImage       = new Texture2D(expected.width, expected.height, TextureFormat.RGB24, false);
                                    var diffPixelsArray = new Color32[expected.width * expected.height];
                                    diffPixels.CopyTo(diffPixelsArray);
                                    diffImage.SetPixels32(diffPixelsArray, 0);
                                    diffImage.Apply(false);

                                    TestContext.CurrentContext.Test.Properties.Set("DiffImage", Convert.ToBase64String(diffImage.EncodeToPNG()));

                                    failedImageMessage.DiffImage     = diffImage.EncodeToPNG();
                                    failedImageMessage.ExpectedImage = expected.EncodeToPNG();
                                    throw;
                                }
                            }
            }
            catch (AssertionException)
            {
                failedImageMessage.ActualImage = actual.EncodeToPNG();
#if UNITY_EDITOR
                ImageHandler.instance.SaveImage(failedImageMessage);
#else
                PlayerConnection.instance.Send(FailedImageMessage.MessageId, failedImageMessage.Serialize());
#endif
                TestContext.CurrentContext.Test.Properties.Set("Image", Convert.ToBase64String(actual.EncodeToPNG()));
                throw;
            }
        }