Skip to content

Commit

Permalink
Add shadow sampler LOD tests for cubemaps
Browse files Browse the repository at this point in the history
Added tests for GLSL 3.00 shadow samplers
in fragment shaders with TEXTURE_CUBE_MAP
target.

Bug: angleproject:365066518
Change-Id: I2b8577310ea5c258d4d13611607f5c4d9be57e04
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5865112
Reviewed-by: Shahbaz Youssefi <[email protected]>
Commit-Queue: Shahbaz Youssefi <[email protected]>
  • Loading branch information
lexaknyazev authored and Angle LUCI CQ committed Sep 16, 2024
1 parent 5e45d53 commit b5280aa
Show file tree
Hide file tree
Showing 2 changed files with 199 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/tests/angle_end2end_tests_expectations.txt
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,7 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen
// Simulator does not support compare functions in the sampler state
365066518 IOS METAL : ShadowSamplerFunctionTexture2DTest.Test/* = SKIP
365066518 IOS METAL : ShadowSamplerFunctionTexture2DArrayTest.Test/* = SKIP
365066518 IOS METAL : ShadowSamplerFunctionTextureCubeTest.Test/* = SKIP

// D3D11 backend does not support LOD options with shadow samplers
365066518 D3D11 : ShadowSamplerFunctionTexture2DTest.Test/*__TextureBias_Mipmapped = SKIP
Expand All @@ -919,6 +920,8 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen
365066518 D3D11 : ShadowSamplerFunctionTexture2DTest.Test/*__TextureProjGradOffset_Mipmapped = SKIP
365066518 D3D11 : ShadowSamplerFunctionTexture2DArrayTest.Test/*__TextureGrad_Mipmapped = SKIP
365066518 D3D11 : ShadowSamplerFunctionTexture2DArrayTest.Test/*__TextureGradOffset_Mipmapped = SKIP
365066518 D3D11 : ShadowSamplerFunctionTextureCubeTest.Test/*__TextureBias_Mipmapped = SKIP
365066518 D3D11 : ShadowSamplerFunctionTextureCubeTest.Test/*__TextureGrad_Mipmapped = SKIP

// Metal on AMD does not support shadow samplers with explicit derivatives
365066518 MAC METAL AMD : ShadowSamplerFunctionTexture2DTest.Test/*__TextureGrad_* = SKIP
Expand All @@ -927,6 +930,7 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen
365066518 MAC METAL AMD : ShadowSamplerFunctionTexture2DTest.Test/*__TextureProjGradOffset_* = SKIP
365066518 MAC METAL AMD : ShadowSamplerFunctionTexture2DArrayTest.Test/*__TextureGrad_* = SKIP
365066518 MAC METAL AMD : ShadowSamplerFunctionTexture2DArrayTest.Test/*__TextureGradOffset_* = SKIP
365066518 MAC METAL AMD : ShadowSamplerFunctionTextureCubeTest.Test/*__TextureGrad_* = SKIP

// Intel macOS OpenGL drivers incorrectly apply explicit derivatives to shadow samplers
365066518 MAC OPENGL INTEL : ShadowSamplerFunctionTexture2DTest.Test/*__TextureGrad_* = SKIP
Expand All @@ -935,6 +939,7 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen
365066518 MAC OPENGL INTEL : ShadowSamplerFunctionTexture2DTest.Test/*__TextureProjGradOffset_* = SKIP
365066518 MAC OPENGL INTEL : ShadowSamplerFunctionTexture2DArrayTest.Test/*__TextureGrad_* = SKIP
365066518 MAC OPENGL INTEL : ShadowSamplerFunctionTexture2DArrayTest.Test/*__TextureGradOffset_* = SKIP
365066518 MAC OPENGL INTEL : ShadowSamplerFunctionTextureCubeTest.Test/*__TextureGrad_* = SKIP

// Some drivers incorrectly apply LOD and bias options when an offset is used
365066518 PIXEL4ORXL GLES : ShadowSamplerFunctionTexture2DTest.Test/*__TextureLodOffset_Mipmapped = SKIP
Expand All @@ -951,6 +956,7 @@ b/330697097 PIXEL6 VULKAN : FramebufferTest_ES31.MultisampleResolveBothAttachmen
365066518 PIXEL6 VULKAN : ShadowSamplerFunctionTexture2DTest.Test/*__TextureProjGradOffset_NonMipmapped = SKIP
365066518 PIXEL6 VULKAN : ShadowSamplerFunctionTexture2DArrayTest.Test/*__TextureGrad_NonMipmapped = SKIP
365066518 PIXEL6 VULKAN : ShadowSamplerFunctionTexture2DArrayTest.Test/*__TextureGradOffset_NonMipmapped = SKIP
365066518 PIXEL6 VULKAN : ShadowSamplerFunctionTextureCubeTest.Test/*__TextureGrad_NonMipmapped = SKIP

// Test is disabled as it only pertains to desktop GLSL
42264721 : GLSLTest_ES31.InterpolateAtWithSwizzle/* = SKIP
Expand Down
193 changes: 193 additions & 0 deletions src/tests/gl_tests/ShadowSamplerFunctionsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,17 @@ constexpr bool RequiresExtensionFor2DArray(FunctionType function)
}
}

constexpr bool RequiresExtensionForCube(FunctionType function)
{
switch (function)
{
case FunctionType::TextureLod:
return true;
default:
return false;
}
}

bool Compare(float reference, float sampled, GLenum op)
{
switch (op)
Expand Down Expand Up @@ -435,6 +446,66 @@ class ShadowSamplerFunctionTexture2DArrayTest : public ShadowSamplerFunctionTest
}
};

class ShadowSamplerFunctionTextureCubeTest : public ShadowSamplerFunctionTestBase
{
protected:
void setupProgramCube(FunctionType function, bool useShadowSampler)
{
ASSERT_FALSE(IsProj(function));
std::stringstream fragmentSource;
fragmentSource << "#version 300 es\n"
<< "#extension GL_EXT_texture_shadow_lod : enable\n"
<< "precision mediump float;\n"
<< "precision mediump samplerCube;\n"
<< "precision mediump samplerCubeShadow;\n"
<< "uniform float dRef;\n"
<< "uniform samplerCube" << (useShadowSampler ? "Shadow" : "") << " tex;\n"
<< "in vec4 v_position;\n"
<< "out vec4 my_FragColor;\n"
<< "void main()\n"
<< "{\n"
<< " vec3 texcoord = vec3(1.0, v_position.xy);\n"
<< " float r = " << FunctionName(function) << "(tex, ";
if (useShadowSampler)
{
fragmentSource << "vec4(texcoord, dRef)";
}
else
{
fragmentSource << "vec3(texcoord)";
}

if (HasLOD(function))
{
fragmentSource << ", 2.0";
}
else if (HasGrad(function))
{
fragmentSource << ", vec3(0.0, 0.34, 0.34), vec3(0.0)";
}

if (HasBias(function))
{
fragmentSource << ", 3.0";
}

fragmentSource << ")" << (useShadowSampler ? "" : ".r") << ";\n";
if (useShadowSampler)
{
fragmentSource << " my_FragColor = vec4(0.0, r, 1.0 - r, 1.0);\n";
}
else
{
fragmentSource << " my_FragColor = vec4(r, 0.0, 0.0, 1.0);\n";
}
fragmentSource << "}";

ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Passthrough(), fragmentSource.str().c_str());
glUseProgram(program);
mPrg = program;
}
};

constexpr GLenum kCompareFuncs[] = {
GL_LEQUAL, GL_GEQUAL, GL_LESS, GL_GREATER, GL_EQUAL, GL_NOTEQUAL, GL_ALWAYS, GL_NEVER,
};
Expand Down Expand Up @@ -652,6 +723,114 @@ TEST_P(ShadowSamplerFunctionTexture2DArrayTest, Test)
}
}

// Test TEXTURE_CUBE_MAP with shadow samplers
TEST_P(ShadowSamplerFunctionTextureCubeTest, Test)
{
FunctionType function;
bool mipmapped;
ParseShadowSamplerFunctionVariationsTestParams(GetParam(), &function, &mipmapped);

if (RequiresExtensionForCube(function))
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_shadow_lod"));
}

GLTexture tex;
const std::vector<GLfloat> level0(64, 0.125f);
const std::vector<GLfloat> level1(16, 0.5f);
const std::vector<GLfloat> level2(4, 0.25f);
const std::vector<GLfloat> level3(1, 0.75f);

glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 4, GL_DEPTH_COMPONENT32F, 8, 8);
for (const GLenum face : {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z})
{
glTexSubImage2D(face, 0, 0, 0, 8, 8, GL_DEPTH_COMPONENT, GL_FLOAT, level0.data());
glTexSubImage2D(face, 1, 0, 0, 4, 4, GL_DEPTH_COMPONENT, GL_FLOAT, level1.data());
glTexSubImage2D(face, 2, 0, 0, 2, 2, GL_DEPTH_COMPONENT, GL_FLOAT, level2.data());
glTexSubImage2D(face, 3, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, level3.data());
}

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,
mipmapped ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
ASSERT_GL_NO_ERROR();

float expectedSample;
if (mipmapped)
{
if (HasBias(function))
{
// Base level 8x8, viewport 8x8, bias 3.0
expectedSample = level3[0];
}
else if (HasLOD(function))
{
// Explicitly requested level 2
expectedSample = level2[0];
}
else if (HasGrad(function))
{
// Cube screen space derivatives should be projected as 0.17
// on the +X face and resolved to level 1 for a 8x8 texture
expectedSample = level1[0];
}
else // implicit LOD
{
// Base level 8x8, viewport 8x8, no bias
expectedSample = level0[0];
}
}
else
{
// LOD options must have no effect when the texture is not mipmapped.
expectedSample = level0[0];
}

glViewport(0, 0, 8, 8);
glClearColor(1.0, 0.0, 1.0, 1.0);

// First sample the texture directly for easier debugging
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_NONE);
setupProgramCube(function, false);
ASSERT_GL_NO_ERROR();

glClear(GL_COLOR_BUFFER_BIT);
drawQuad(mPrg, essl3_shaders::PositionAttrib(), 0.0f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(expectedSample * 255.0, 0, 0, 255), 1);

// Try shadow samplers
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
setupProgramCube(function, true);
const GLint loc = glGetUniformLocation(mPrg, "dRef");
for (const float refValue : kRefValues)
{
glUniform1f(loc, refValue);
for (const GLenum compareFunc : kCompareFuncs)
{
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, compareFunc);
ASSERT_GL_NO_ERROR();

glClear(GL_COLOR_BUFFER_BIT);
drawQuad(mPrg, essl3_shaders::PositionAttrib(), 0.0f);
if (Compare(refValue, expectedSample, compareFunc))
{
EXPECT_PIXEL_COLOR_EQ(4, 4, GLColor::green)
<< gl::GLenumToString(gl::GLESEnum::DepthFunction, compareFunc)
<< ", reference " << refValue << ", expected sample " << expectedSample;
}
else
{
EXPECT_PIXEL_COLOR_EQ(4, 4, GLColor::blue)
<< gl::GLenumToString(gl::GLESEnum::DepthFunction, compareFunc)
<< ", reference " << refValue << ", expected sample " << expectedSample;
}
}
}
}

constexpr FunctionType kTexture2DFunctionTypes[] = {
FunctionType::Texture, FunctionType::TextureBias,
FunctionType::TextureOffset, FunctionType::TextureOffsetBias,
Expand All @@ -670,6 +849,13 @@ constexpr FunctionType kTexture2DArrayFunctionTypes[] = {
FunctionType::TextureGrad, FunctionType::TextureGradOffset,
};

constexpr FunctionType kTextureCubeFunctionTypes[] = {
FunctionType::Texture,
FunctionType::TextureBias,
FunctionType::TextureLod,
FunctionType::TextureGrad,
};

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShadowSamplerFunctionTexture2DTest);
ANGLE_INSTANTIATE_TEST_COMBINE_2(ShadowSamplerFunctionTexture2DTest,
ShadowSamplerFunctionVariationsTestPrint,
Expand All @@ -684,4 +870,11 @@ ANGLE_INSTANTIATE_TEST_COMBINE_2(ShadowSamplerFunctionTexture2DArrayTest,
testing::Bool(),
ANGLE_ALL_TEST_PLATFORMS_ES3);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShadowSamplerFunctionTextureCubeTest);
ANGLE_INSTANTIATE_TEST_COMBINE_2(ShadowSamplerFunctionTextureCubeTest,
ShadowSamplerFunctionVariationsTestPrint,
testing::ValuesIn(kTextureCubeFunctionTypes),
testing::Bool(),
ANGLE_ALL_TEST_PLATFORMS_ES3);

} // anonymous namespace

0 comments on commit b5280aa

Please sign in to comment.