From a1772f342142d30d3dad0974cc6b3db64af23ca7 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 22 Dec 2024 17:39:59 +0100 Subject: [PATCH] Add unit tests for new readonly texture interfaces --- .../ResourceDimensionsTests.g.cs | 105 ++++++++++++++++++ .../ResourceDimensionsTests.tt | 15 ++- tests/ComputeSharp.Tests/Texture1DTests.cs | 43 +++++++ tests/ComputeSharp.Tests/Texture2DTests.cs | 43 +++++++ tests/ComputeSharp.Tests/Texture3DTests.cs | 43 +++++++ 5 files changed, 247 insertions(+), 2 deletions(-) diff --git a/tests/ComputeSharp.Tests/ResourceDimensionsTests.g.cs b/tests/ComputeSharp.Tests/ResourceDimensionsTests.g.cs index 7dafbcf2a..b75c1956a 100644 --- a/tests/ComputeSharp.Tests/ResourceDimensionsTests.g.cs +++ b/tests/ComputeSharp.Tests/ResourceDimensionsTests.g.cs @@ -109,6 +109,40 @@ public void Execute() } } + [CombinatorialTestMethod] + [AllDevices] + [Data(8)] + [Data(64)] + [Data(128)] + [Data(376)] + public void ReadOnlyTexture1D_T1_AsIReadOnlyTexture1D(Device device, int axis0) + { + using ReadOnlyTexture1D resource = device.Get().AllocateReadOnlyTexture1D(axis0); + using ReadWriteBuffer result = device.Get().AllocateReadWriteBuffer(1); + + device.Get().For(1, new ReadOnlyTexture1D_T1_AsIReadOnlyTexture1DShader(resource, result)); + + int[] dimensions = result.ToArray(); + + CollectionAssert.AreEqual( + expected: new[] { axis0 }, + actual: dimensions); + } + + [AutoConstructor] + [ThreadGroupSize(DefaultThreadGroupSizes.X)] + [GeneratedComputeShaderDescriptor] + internal readonly partial struct ReadOnlyTexture1D_T1_AsIReadOnlyTexture1DShader : IComputeShader + { + public readonly IReadOnlyTexture1D source; + public readonly ReadWriteBuffer result; + + public void Execute() + { + result[0] = source.Width; + } + } + [CombinatorialTestMethod] [AllDevices] [Data(8)] @@ -352,6 +386,41 @@ public void Execute() } } + [CombinatorialTestMethod] + [AllDevices] + [Data(8, 12)] + [Data(64, 13)] + [Data(128, 32)] + [Data(376, 112)] + public void ReadOnlyTexture2D_T1_AsIReadOnlyTexture2D(Device device, int axis0, int axis1) + { + using ReadOnlyTexture2D resource = device.Get().AllocateReadOnlyTexture2D(axis0, axis1); + using ReadWriteBuffer result = device.Get().AllocateReadWriteBuffer(2); + + device.Get().For(1, new ReadOnlyTexture2D_T1_AsIReadOnlyTexture2DShader(resource, result)); + + int[] dimensions = result.ToArray(); + + CollectionAssert.AreEqual( + expected: new[] { axis0, axis1 }, + actual: dimensions); + } + + [AutoConstructor] + [ThreadGroupSize(DefaultThreadGroupSizes.X)] + [GeneratedComputeShaderDescriptor] + internal readonly partial struct ReadOnlyTexture2D_T1_AsIReadOnlyTexture2DShader : IComputeShader + { + public readonly IReadOnlyTexture2D source; + public readonly ReadWriteBuffer result; + + public void Execute() + { + result[0] = source.Width; + result[1] = source.Height; + } + } + [CombinatorialTestMethod] [AllDevices] [Data(8, 12)] @@ -602,6 +671,42 @@ public void Execute() } } + [CombinatorialTestMethod] + [AllDevices] + [Data(8, 12, 3)] + [Data(64, 24, 4)] + [Data(128, 32, 4)] + [Data(376, 64, 3)] + public void ReadOnlyTexture3D_T1_AsIReadOnlyTexture3D(Device device, int axis0, int axis1, int axis2) + { + using ReadOnlyTexture3D resource = device.Get().AllocateReadOnlyTexture3D(axis0, axis1, axis2); + using ReadWriteBuffer result = device.Get().AllocateReadWriteBuffer(3); + + device.Get().For(1, new ReadOnlyTexture3D_T1_AsIReadOnlyTexture3DShader(resource, result)); + + int[] dimensions = result.ToArray(); + + CollectionAssert.AreEqual( + expected: new[] { axis0, axis1, axis2 }, + actual: dimensions); + } + + [AutoConstructor] + [ThreadGroupSize(DefaultThreadGroupSizes.X)] + [GeneratedComputeShaderDescriptor] + internal readonly partial struct ReadOnlyTexture3D_T1_AsIReadOnlyTexture3DShader : IComputeShader + { + public readonly IReadOnlyTexture3D source; + public readonly ReadWriteBuffer result; + + public void Execute() + { + result[0] = source.Width; + result[1] = source.Height; + result[2] = source.Depth; + } + } + [CombinatorialTestMethod] [AllDevices] [Data(8, 12, 3)] diff --git a/tests/ComputeSharp.Tests/ResourceDimensionsTests.tt b/tests/ComputeSharp.Tests/ResourceDimensionsTests.tt index 4fbf185ba..1fd3e2a27 100644 --- a/tests/ComputeSharp.Tests/ResourceDimensionsTests.tt +++ b/tests/ComputeSharp.Tests/ResourceDimensionsTests.tt @@ -37,17 +37,20 @@ var typesMap = new Dictionary var interfacesMap = new Dictionary { ["ReadWriteTexture1D"] = "IReadOnlyTexture1D", + ["ReadOnlyTexture1D"] = "IReadOnlyTexture1D", ["ReadOnlyTexture1D"] = "IReadOnlyNormalizedTexture1D", ["ReadWriteTexture1D"] = "IReadWriteNormalizedTexture1D", ["ReadWriteTexture2D"] = "IReadOnlyTexture2D", + ["ReadOnlyTexture2D"] = "IReadOnlyTexture2D", ["ReadOnlyTexture2D"] = "IReadOnlyNormalizedTexture2D", ["ReadWriteTexture2D"] = "IReadWriteNormalizedTexture2D", ["ReadWriteTexture3D"] = "IReadOnlyTexture3D", + ["ReadOnlyTexture3D"] = "IReadOnlyTexture3D", ["ReadOnlyTexture3D"] = "IReadOnlyNormalizedTexture3D", ["ReadWriteTexture3D"] = "IReadWriteNormalizedTexture3D" }; -// Map of all resource that need a readonly wrapper +// Map of all resource interface types that need a readonly wrapper var readonlyWrappersMap = new HashSet { "IReadOnlyTexture1D", @@ -55,6 +58,14 @@ var readonlyWrappersMap = new HashSet "IReadOnlyTexture3D" }; +// Map of all resource concrete types that do not need a readonly wrapper +var explicitReadonlyWrappersMap = new HashSet +{ + "ReadOnlyTexture1D", + "ReadOnlyTexture2D", + "ReadOnlyTexture3D" +}; + // Map of data row items to test multiple dimension combinations var dataRows = new Dictionary { @@ -97,7 +108,7 @@ foreach (var pair in typesMap) .Range(0, numberOfDimensions) .Select(x => $"axis{x}")); - bool needsReadonlyWrapper = readonlyWrappersMap.Contains(shaderResourceType); + bool needsReadonlyWrapper = readonlyWrappersMap.Contains(shaderResourceType) && !explicitReadonlyWrappersMap.Contains(pair.Key); #> public void <#=testMethodName#>(Device device, <#=parameters#>) { diff --git a/tests/ComputeSharp.Tests/Texture1DTests.cs b/tests/ComputeSharp.Tests/Texture1DTests.cs index 17b48c5e4..9101c20e1 100644 --- a/tests/ComputeSharp.Tests/Texture1DTests.cs +++ b/tests/ComputeSharp.Tests/Texture1DTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using ComputeSharp.Resources; using ComputeSharp.Tests.Attributes; @@ -406,4 +407,46 @@ public void Execute() this.destination[ThreadIds.X] = this.source[ThreadIds.X]; } } + + [CombinatorialTestMethod] + [AllDevices] + public void Dispatch_ReadWriteTexture1D_AsInterface_FromReadOnly(Device device) + { + float[] data = Enumerable.Range(0, 256).Select(static i => (float)i).ToArray(); + + using ReadOnlyTexture1D source = device.Get().AllocateReadOnlyTexture1D(data); + using ReadWriteBuffer buffer1 = device.Get().AllocateReadWriteBuffer(data.Length); + using ReadWriteBuffer buffer2 = device.Get().AllocateReadWriteBuffer(data.Length); + + device.Get().For(source.Width, new InterfaceReadOnlyTexture1DKernel(source, buffer1, buffer2)); + + float[] result1 = buffer1.ToArray(); + float[] result2 = buffer2.ToArray(); + + CollectionAssert.AreEqual( + expected: data, + actual: result1, + comparer: Comparer.Create(static (x, y) => Math.Abs(x - y) < 0.000001f ? 0 : x.CompareTo(y))); + + CollectionAssert.AreEqual( + expected: data, + actual: result2, + comparer: Comparer.Create(static (x, y) => Math.Abs(x - y) < 0.000001f ? 0 : x.CompareTo(y))); + } + + [AutoConstructor] + [ThreadGroupSize(DefaultThreadGroupSizes.X)] + [GeneratedComputeShaderDescriptor] + internal readonly partial struct InterfaceReadOnlyTexture1DKernel : IComputeShader + { + public readonly IReadOnlyTexture1D source; + public readonly ReadWriteBuffer buffer1; + public readonly ReadWriteBuffer buffer2; + + public void Execute() + { + this.buffer1[ThreadIds.X] = this.source[ThreadIds.X]; + this.buffer2[ThreadIds.X] = this.source.Sample(ThreadIds.X); + } + } } \ No newline at end of file diff --git a/tests/ComputeSharp.Tests/Texture2DTests.cs b/tests/ComputeSharp.Tests/Texture2DTests.cs index 82fb8171b..6e6066c30 100644 --- a/tests/ComputeSharp.Tests/Texture2DTests.cs +++ b/tests/ComputeSharp.Tests/Texture2DTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using CommunityToolkit.HighPerformance; using ComputeSharp.Resources; @@ -471,4 +472,46 @@ public void Execute() this.destination[ThreadIds.XY] = this.source[ThreadIds.XY]; } } + + [CombinatorialTestMethod] + [AllDevices] + public void Dispatch_ReadWriteTexture2D_AsInterface_FromReadOnly(Device device) + { + float[] data = Enumerable.Range(0, 32 * 32).Select(static i => (float)i).ToArray(); + + using ReadOnlyTexture2D source = device.Get().AllocateReadOnlyTexture2D(data, 32, 32); + using ReadWriteTexture2D texture1 = device.Get().AllocateReadWriteTexture2D(32, 32); + using ReadWriteTexture2D texture2 = device.Get().AllocateReadWriteTexture2D(32, 32); + + device.Get().For(source.Width, new InterfaceReadOnlyTexture2DKernel(source, texture1, texture2)); + + float[] result1 = texture1.ToArray().AsSpan().ToArray(); + float[] result2 = texture2.ToArray().AsSpan().ToArray(); + + CollectionAssert.AreEqual( + expected: data, + actual: result1, + comparer: Comparer.Create(static (x, y) => Math.Abs(x - y) < 0.000001f ? 0 : x.CompareTo(y))); + + CollectionAssert.AreEqual( + expected: data, + actual: result2, + comparer: Comparer.Create(static (x, y) => Math.Abs(x - y) < 0.000001f ? 0 : x.CompareTo(y))); + } + + [AutoConstructor] + [ThreadGroupSize(DefaultThreadGroupSizes.XY)] + [GeneratedComputeShaderDescriptor] + internal readonly partial struct InterfaceReadOnlyTexture2DKernel : IComputeShader + { + public readonly IReadOnlyTexture2D source; + public readonly ReadWriteTexture2D texture1; + public readonly ReadWriteTexture2D texture2; + + public void Execute() + { + this.texture1[ThreadIds.XY] = this.source[ThreadIds.XY]; + this.texture2[ThreadIds.XY] = this.source.Sample(ThreadIds.XY); + } + } } \ No newline at end of file diff --git a/tests/ComputeSharp.Tests/Texture3DTests.cs b/tests/ComputeSharp.Tests/Texture3DTests.cs index 530eb8524..404cb4b53 100644 --- a/tests/ComputeSharp.Tests/Texture3DTests.cs +++ b/tests/ComputeSharp.Tests/Texture3DTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using CommunityToolkit.HighPerformance; using CommunityToolkit.HighPerformance.Enumerables; @@ -576,4 +577,46 @@ public void Execute() this.destination[ThreadIds.XYZ] = this.source[ThreadIds.XYZ]; } } + + [CombinatorialTestMethod] + [AllDevices] + public void Dispatch_ReadWriteTexture3D_AsInterface_FromReadOnly(Device device) + { + float[] data = Enumerable.Range(0, 32 * 32 * 3).Select(static i => (float)i).ToArray(); + + using ReadOnlyTexture3D source = device.Get().AllocateReadOnlyTexture3D(data, 32, 32, 3); + using ReadWriteTexture3D texture1 = device.Get().AllocateReadWriteTexture3D(32, 32, 3); + using ReadWriteTexture3D texture2 = device.Get().AllocateReadWriteTexture3D(32, 32, 3); + + device.Get().For(source.Width, new InterfaceReadOnlyTexture3DKernel(source, texture1, texture2)); + + float[] result1 = texture1.ToArray().AsSpan().ToArray(); + float[] result2 = texture2.ToArray().AsSpan().ToArray(); + + CollectionAssert.AreEqual( + expected: data, + actual: result1, + comparer: Comparer.Create(static (x, y) => Math.Abs(x - y) < 0.000001f ? 0 : x.CompareTo(y))); + + CollectionAssert.AreEqual( + expected: data, + actual: result2, + comparer: Comparer.Create(static (x, y) => Math.Abs(x - y) < 0.000001f ? 0 : x.CompareTo(y))); + } + + [AutoConstructor] + [ThreadGroupSize(DefaultThreadGroupSizes.XYZ)] + [GeneratedComputeShaderDescriptor] + internal readonly partial struct InterfaceReadOnlyTexture3DKernel : IComputeShader + { + public readonly IReadOnlyTexture3D source; + public readonly ReadWriteTexture3D texture1; + public readonly ReadWriteTexture3D texture2; + + public void Execute() + { + this.texture1[ThreadIds.XYZ] = this.source[ThreadIds.XYZ]; + this.texture2[ThreadIds.XYZ] = this.source.Sample(ThreadIds.XYZ); + } + } } \ No newline at end of file