163 lines
7.3 KiB
C#
163 lines
7.3 KiB
C#
using System.Runtime.InteropServices;
|
|
using AcDream.App.Rendering.Gpu;
|
|
using AcDream.App.Rendering.Gpu.Vk;
|
|
using AcDream.App.Rendering.Packs;
|
|
using AcDream.Plugin.Abstractions.Rendering;
|
|
|
|
namespace AcDream.App.Tests.Rendering.Packs;
|
|
|
|
public sealed class AtmosphericShaderAbiTests
|
|
{
|
|
[Fact]
|
|
public void HostStructsMatchTheCheckedInStd140AtmosphericAbi()
|
|
{
|
|
Assert.Equal(160, Marshal.SizeOf<AtmosphericFrameUniforms>());
|
|
Assert.Equal(0, Offset<AtmosphericFrameUniforms>(nameof(AtmosphericFrameUniforms.SunScreen)));
|
|
Assert.Equal(16, Offset<AtmosphericFrameUniforms>(nameof(AtmosphericFrameUniforms.SunColor)));
|
|
Assert.Equal(32, Offset<AtmosphericFrameUniforms>(nameof(AtmosphericFrameUniforms.Viewport)));
|
|
Assert.Equal(48, Offset<AtmosphericFrameUniforms>(nameof(AtmosphericFrameUniforms.Weather)));
|
|
Assert.Equal(64, Offset<AtmosphericFrameUniforms>(nameof(AtmosphericFrameUniforms.SunDirection)));
|
|
Assert.Equal(80, Offset<AtmosphericFrameUniforms>(nameof(AtmosphericFrameUniforms.Policy)));
|
|
Assert.Equal(96, Offset<AtmosphericFrameUniforms>(nameof(AtmosphericFrameUniforms.InverseViewProjection)));
|
|
|
|
Assert.Equal(64, Marshal.SizeOf<AtmosphericPackPassUniforms>());
|
|
Assert.Equal(0, Offset<AtmosphericPackPassUniforms>(nameof(AtmosphericPackPassUniforms.Params0)));
|
|
Assert.Equal(16, Offset<AtmosphericPackPassUniforms>(nameof(AtmosphericPackPassUniforms.Params1)));
|
|
Assert.Equal(32, Offset<AtmosphericPackPassUniforms>(nameof(AtmosphericPackPassUniforms.Params2)));
|
|
Assert.Equal(48, Offset<AtmosphericPackPassUniforms>(nameof(AtmosphericPackPassUniforms.Params3)));
|
|
Assert.Equal(256, Marshal.SizeOf<PackSettingsUniforms>());
|
|
|
|
Assert.Equal(5u, GpuBindingModel.UniformAtmosphericFrame);
|
|
Assert.Equal(6u, GpuBindingModel.UniformDirectionalShadow);
|
|
Assert.Equal(7u, GpuBindingModel.UniformPackPass);
|
|
Assert.Equal(8u, GpuBindingModel.UniformPackSettings);
|
|
Assert.Equal(5, VulkanFrameBindings.UniformBindingCount);
|
|
Assert.Equal(
|
|
[1u, 2u, 3u, 4u],
|
|
VulkanPipelineLayouts.DeclaredUniformBindings);
|
|
Assert.Equal(3, RenderPackShaderAbi.UniformDescriptorSet);
|
|
Assert.Equal(3u, GpuBindingModel.RenderPackUniformSet);
|
|
Assert.False(VulkanPipelineLayouts.IsDeclaredUniformBinding(5));
|
|
Assert.True(VulkanPipelineLayouts.IsDeclaredPackUniformBinding(5));
|
|
Assert.True(VulkanPipelineLayouts.IsDeclaredPackUniformBinding(8));
|
|
|
|
Assert.Equal(RenderPackShaderAbi.AtmosphericFrameBinding, (int)GpuBindingModel.UniformAtmosphericFrame);
|
|
Assert.Equal(RenderPackShaderAbi.AtmosphericFrameSizeBytes, AtmosphericFrameUniforms.SizeInBytes);
|
|
Assert.Equal(RenderPackShaderAbi.DirectionalShadowBinding, (int)GpuBindingModel.UniformDirectionalShadow);
|
|
Assert.Equal(RenderPackShaderAbi.PackPassBinding, (int)GpuBindingModel.UniformPackPass);
|
|
Assert.Equal(RenderPackShaderAbi.PackPassSizeBytes, AtmosphericPackPassUniforms.SizeInBytes);
|
|
Assert.Equal(RenderPackShaderAbi.PackSettingsBinding, (int)GpuBindingModel.UniformPackSettings);
|
|
Assert.Equal(RenderPackShaderAbi.PackSettingsSizeBytes, PackSettingsUniforms.SizeInBytes);
|
|
Assert.Equal(RenderPackShaderAbi.PushConstantSizeBytes, GpuBindingModel.PushConstantBytes);
|
|
}
|
|
|
|
[Fact]
|
|
public void CheckedInCommonIncludeNamesTheSameBindingsAndMemberOrder()
|
|
{
|
|
string text = File.ReadAllText(Path.Combine(
|
|
RepositoryRoot(),
|
|
"src",
|
|
"AcDream.App",
|
|
"Rendering",
|
|
"Shaders",
|
|
"atmospheric_common.glsl"));
|
|
|
|
AssertOrdered(text,
|
|
"ACDREAM_PACK_UBO_SET binding = 5",
|
|
"uAtmosphereSunScreen",
|
|
"uAtmosphereSunColor",
|
|
"uAtmosphereViewport",
|
|
"uAtmosphereWeather",
|
|
"uAtmosphereSunDirection",
|
|
"uAtmospherePolicy",
|
|
"uAtmosphereInverseViewProjection",
|
|
"binding = 7",
|
|
"uPackParams0",
|
|
"uPackParams1",
|
|
"uPackParams2",
|
|
"uPackParams3",
|
|
"FusedAtmosphericPostProcess PackPass ABI",
|
|
"binding = 8",
|
|
"uPackSettings[16]");
|
|
}
|
|
|
|
[Fact]
|
|
public void FusedLowShadersRetainTheDeclaredOcclusionAndBloomPixelKernels()
|
|
{
|
|
string shaderRoot = Path.Combine(
|
|
RepositoryRoot(),
|
|
"src",
|
|
"AcDream.App",
|
|
"Rendering",
|
|
"Shaders");
|
|
string occlusion = File.ReadAllText(Path.Combine(
|
|
shaderRoot,
|
|
"atmospheric_sun_occlusion.frag"));
|
|
string rays = File.ReadAllText(Path.Combine(
|
|
shaderRoot,
|
|
"atmospheric_sun_rays.frag"));
|
|
string blur = File.ReadAllText(Path.Combine(
|
|
shaderRoot,
|
|
"atmospheric_bloom_blur.frag"));
|
|
string downsample = File.ReadAllText(Path.Combine(
|
|
shaderRoot,
|
|
"atmospheric_bloom_downsample.frag"));
|
|
string filmic = File.ReadAllText(Path.Combine(
|
|
shaderRoot,
|
|
"atmospheric_filmic.frag"));
|
|
|
|
foreach (string threshold in (string[])["0.9975", "0.99995"])
|
|
{
|
|
Assert.Contains(threshold, occlusion, StringComparison.Ordinal);
|
|
Assert.Contains(threshold, rays, StringComparison.Ordinal);
|
|
}
|
|
foreach (string kernel in (string[])
|
|
["0.227027", "0.316216", "1.384615", "0.070270", "3.230769"])
|
|
{
|
|
Assert.Contains(kernel, blur, StringComparison.Ordinal);
|
|
Assert.Contains(kernel, filmic, StringComparison.Ordinal);
|
|
}
|
|
Assert.Contains("round(clamp(unobstructedSky * enabled", rays,
|
|
StringComparison.Ordinal);
|
|
Assert.Contains("uPackParams1.z > 0.5", filmic,
|
|
StringComparison.Ordinal);
|
|
Assert.Contains("brightness - threshold + knee", filmic,
|
|
StringComparison.Ordinal);
|
|
foreach (string extraction in (string[])
|
|
["0.2126", "0.7152", "0.0722", "brightness - threshold + knee"])
|
|
{
|
|
Assert.Contains(extraction, downsample, StringComparison.Ordinal);
|
|
Assert.Contains(extraction, filmic, StringComparison.Ordinal);
|
|
}
|
|
const double oneDimensionalWeight =
|
|
0.227027 + (2 * 0.316216) + (2 * 0.070270);
|
|
Assert.InRange(
|
|
oneDimensionalWeight * oneDimensionalWeight,
|
|
0.99999,
|
|
1.00001);
|
|
}
|
|
|
|
private static int Offset<T>(string field) where T : struct =>
|
|
Marshal.OffsetOf<T>(field).ToInt32();
|
|
|
|
private static void AssertOrdered(string text, params string[] tokens)
|
|
{
|
|
int prior = -1;
|
|
foreach (string token in tokens)
|
|
{
|
|
int next = text.IndexOf(token, prior + 1, StringComparison.Ordinal);
|
|
Assert.True(next > prior, $"'{token}' is missing or out of ABI order.");
|
|
prior = next;
|
|
}
|
|
}
|
|
|
|
private static string RepositoryRoot()
|
|
{
|
|
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
|
while (directory is not null
|
|
&& !File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
|
|
directory = directory.Parent;
|
|
return directory?.FullName
|
|
?? throw new InvalidOperationException("Could not locate repository root.");
|
|
}
|
|
}
|