Skip to content

Commit

Permalink
Add unit tests for new readonly texture interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergio0694 committed Dec 22, 2024
1 parent 0c02537 commit a1772f3
Show file tree
Hide file tree
Showing 5 changed files with 247 additions and 2 deletions.
105 changes: 105 additions & 0 deletions tests/ComputeSharp.Tests/ResourceDimensionsTests.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<float> resource = device.Get().AllocateReadOnlyTexture1D<float>(axis0);
using ReadWriteBuffer<int> result = device.Get().AllocateReadWriteBuffer<int>(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<float> source;
public readonly ReadWriteBuffer<int> result;

public void Execute()
{
result[0] = source.Width;
}
}

[CombinatorialTestMethod]
[AllDevices]
[Data(8)]
Expand Down Expand Up @@ -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<float> resource = device.Get().AllocateReadOnlyTexture2D<float>(axis0, axis1);
using ReadWriteBuffer<int> result = device.Get().AllocateReadWriteBuffer<int>(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<float> source;
public readonly ReadWriteBuffer<int> result;

public void Execute()
{
result[0] = source.Width;
result[1] = source.Height;
}
}

[CombinatorialTestMethod]
[AllDevices]
[Data(8, 12)]
Expand Down Expand Up @@ -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<float> resource = device.Get().AllocateReadOnlyTexture3D<float>(axis0, axis1, axis2);
using ReadWriteBuffer<int> result = device.Get().AllocateReadWriteBuffer<int>(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<float> source;
public readonly ReadWriteBuffer<int> result;

public void Execute()
{
result[0] = source.Width;
result[1] = source.Height;
result[2] = source.Depth;
}
}

[CombinatorialTestMethod]
[AllDevices]
[Data(8, 12, 3)]
Expand Down
15 changes: 13 additions & 2 deletions tests/ComputeSharp.Tests/ResourceDimensionsTests.tt
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,35 @@ var typesMap = new Dictionary<string, string[]>
var interfacesMap = new Dictionary<string, string>
{
["ReadWriteTexture1D<float>"] = "IReadOnlyTexture1D<float>",
["ReadOnlyTexture1D<float>"] = "IReadOnlyTexture1D<float>",
["ReadOnlyTexture1D<Rgba32, float4>"] = "IReadOnlyNormalizedTexture1D<float4>",
["ReadWriteTexture1D<Rgba32, float4>"] = "IReadWriteNormalizedTexture1D<float4>",
["ReadWriteTexture2D<float>"] = "IReadOnlyTexture2D<float>",
["ReadOnlyTexture2D<float>"] = "IReadOnlyTexture2D<float>",
["ReadOnlyTexture2D<Rgba32, float4>"] = "IReadOnlyNormalizedTexture2D<float4>",
["ReadWriteTexture2D<Rgba32, float4>"] = "IReadWriteNormalizedTexture2D<float4>",
["ReadWriteTexture3D<float>"] = "IReadOnlyTexture3D<float>",
["ReadOnlyTexture3D<float>"] = "IReadOnlyTexture3D<float>",
["ReadOnlyTexture3D<Rgba32, float4>"] = "IReadOnlyNormalizedTexture3D<float4>",
["ReadWriteTexture3D<Rgba32, float4>"] = "IReadWriteNormalizedTexture3D<float4>"
};

// Map of all resource that need a readonly wrapper
// Map of all resource interface types that need a readonly wrapper
var readonlyWrappersMap = new HashSet<string>
{
"IReadOnlyTexture1D<float>",
"IReadOnlyTexture2D<float>",
"IReadOnlyTexture3D<float>"
};

// Map of all resource concrete types that do not need a readonly wrapper
var explicitReadonlyWrappersMap = new HashSet<string>
{
"ReadOnlyTexture1D<float>",
"ReadOnlyTexture2D<float>",
"ReadOnlyTexture3D<float>"
};

// Map of data row items to test multiple dimension combinations
var dataRows = new Dictionary<int, int[][]>
{
Expand Down Expand Up @@ -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#>)
{
Expand Down
43 changes: 43 additions & 0 deletions tests/ComputeSharp.Tests/Texture1DTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ComputeSharp.Resources;
using ComputeSharp.Tests.Attributes;
Expand Down Expand Up @@ -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<float> source = device.Get().AllocateReadOnlyTexture1D(data);
using ReadWriteBuffer<float> buffer1 = device.Get().AllocateReadWriteBuffer<float>(data.Length);
using ReadWriteBuffer<float> buffer2 = device.Get().AllocateReadWriteBuffer<float>(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<float>.Create(static (x, y) => Math.Abs(x - y) < 0.000001f ? 0 : x.CompareTo(y)));

CollectionAssert.AreEqual(
expected: data,
actual: result2,
comparer: Comparer<float>.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<float> source;
public readonly ReadWriteBuffer<float> buffer1;
public readonly ReadWriteBuffer<float> buffer2;

public void Execute()
{
this.buffer1[ThreadIds.X] = this.source[ThreadIds.X];
this.buffer2[ThreadIds.X] = this.source.Sample(ThreadIds.X);
}
}
}
43 changes: 43 additions & 0 deletions tests/ComputeSharp.Tests/Texture2DTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.HighPerformance;
using ComputeSharp.Resources;
Expand Down Expand Up @@ -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<float> source = device.Get().AllocateReadOnlyTexture2D(data, 32, 32);
using ReadWriteTexture2D<float> texture1 = device.Get().AllocateReadWriteTexture2D<float>(32, 32);
using ReadWriteTexture2D<float> texture2 = device.Get().AllocateReadWriteTexture2D<float>(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<float>.Create(static (x, y) => Math.Abs(x - y) < 0.000001f ? 0 : x.CompareTo(y)));

CollectionAssert.AreEqual(
expected: data,
actual: result2,
comparer: Comparer<float>.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<float> source;
public readonly ReadWriteTexture2D<float> texture1;
public readonly ReadWriteTexture2D<float> texture2;

public void Execute()
{
this.texture1[ThreadIds.XY] = this.source[ThreadIds.XY];
this.texture2[ThreadIds.XY] = this.source.Sample(ThreadIds.XY);
}
}
}
43 changes: 43 additions & 0 deletions tests/ComputeSharp.Tests/Texture3DTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.HighPerformance;
using CommunityToolkit.HighPerformance.Enumerables;
Expand Down Expand Up @@ -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<float> source = device.Get().AllocateReadOnlyTexture3D(data, 32, 32, 3);
using ReadWriteTexture3D<float> texture1 = device.Get().AllocateReadWriteTexture3D<float>(32, 32, 3);
using ReadWriteTexture3D<float> texture2 = device.Get().AllocateReadWriteTexture3D<float>(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<float>.Create(static (x, y) => Math.Abs(x - y) < 0.000001f ? 0 : x.CompareTo(y)));

CollectionAssert.AreEqual(
expected: data,
actual: result2,
comparer: Comparer<float>.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<float> source;
public readonly ReadWriteTexture3D<float> texture1;
public readonly ReadWriteTexture3D<float> texture2;

public void Execute()
{
this.texture1[ThreadIds.XYZ] = this.source[ThreadIds.XYZ];
this.texture2[ThreadIds.XYZ] = this.source.Sample(ThreadIds.XYZ);
}
}
}

0 comments on commit a1772f3

Please sign in to comment.