// // Copyright 2024 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // These tests assert that textures incompatible with samplers do not cause any runtime errors. #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" using namespace angle; namespace { enum class SamplerType { Float, SignedInteger, UnsignedInteger, Shadow, }; enum class TextureType { UnsignedNormalized, SignedNormalized, Float, UnsignedInteger, SignedInteger, Depth, DepthStencilDepthMode, DepthStencilStencilMode, Stencil, }; enum class TextureCompareMode { None, Ref, }; // Variations corresponding to enums above. using IncompatibleTextureVariationsTestParams = std::tuple; std::ostream &operator<<(std::ostream &out, SamplerType samplerType) { switch (samplerType) { case SamplerType::Float: out << "Float"; break; case SamplerType::SignedInteger: out << "SignedInteger"; break; case SamplerType::UnsignedInteger: out << "UnsignedInteger"; break; case SamplerType::Shadow: out << "Shadow"; break; } return out; } std::ostream &operator<<(std::ostream &out, TextureType textureType) { switch (textureType) { case TextureType::UnsignedNormalized: out << "UnsignedNormalized"; break; case TextureType::SignedNormalized: out << "SignedNormalized"; break; case TextureType::Float: out << "Float"; break; case TextureType::UnsignedInteger: out << "UnsignedInteger"; break; case TextureType::SignedInteger: out << "SignedInteger"; break; case TextureType::Depth: out << "Depth"; break; case TextureType::DepthStencilDepthMode: out << "DepthStencilDepthMode"; break; case TextureType::DepthStencilStencilMode: out << "DepthStencilStencilMode"; break; case TextureType::Stencil: out << "Stencil"; break; } return out; } std::ostream &operator<<(std::ostream &out, TextureCompareMode textureCompareMode) { switch (textureCompareMode) { case TextureCompareMode::None: out << "None"; break; case TextureCompareMode::Ref: out << "Ref"; break; } return out; } void ParseIncompatibleTextureTestParams(const IncompatibleTextureVariationsTestParams ¶ms, SamplerType *samplerTypeOut, TextureType *textureTypeOut, TextureCompareMode *textureCompareModeOut) { *samplerTypeOut = std::get<1>(params); *textureTypeOut = std::get<2>(params); *textureCompareModeOut = std::get<3>(params); } std::string IncompatibleTextureVariationsTestPrint( const ::testing::TestParamInfo ¶msInfo) { const IncompatibleTextureVariationsTestParams ¶ms = paramsInfo.param; std::ostringstream out; out << std::get<0>(params); SamplerType samplerType; TextureType textureType; TextureCompareMode textureCompareMode; ParseIncompatibleTextureTestParams(params, &samplerType, &textureType, &textureCompareMode); out << "__" << "SamplerType" << samplerType << "_" << "TextureType" << textureType << "_" << "TextureCompareMode" << textureCompareMode; return out.str(); } class IncompatibleTextureTest : public ANGLETest {}; // Test that no errors are generated TEST_P(IncompatibleTextureTest, Test) { SamplerType samplerType; TextureType textureType; TextureCompareMode textureCompareMode; ParseIncompatibleTextureTestParams(GetParam(), &samplerType, &textureType, &textureCompareMode); std::stringstream fragmentSource; fragmentSource << "#version 300 es\n" << "out mediump vec4 my_FragColor;\n"; switch (samplerType) { case SamplerType::Float: fragmentSource << "uniform mediump sampler2D tex;\n"; break; case SamplerType::SignedInteger: fragmentSource << "uniform mediump isampler2D tex;\n"; break; case SamplerType::UnsignedInteger: fragmentSource << "uniform mediump usampler2D tex;\n"; break; case SamplerType::Shadow: fragmentSource << "uniform mediump sampler2DShadow tex;\n"; break; } fragmentSource << "void main()\n" << "{\n"; fragmentSource << " my_FragColor = vec4(texture(tex, " << (samplerType == SamplerType::Shadow ? "vec3" : "vec2") << "(0)));\n"; fragmentSource << "}"; ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentSource.str().c_str()); ASSERT_GL_NO_ERROR(); GLTexture tex; glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); switch (textureType) { case TextureType::UnsignedNormalized: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); break; case TextureType::SignedNormalized: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8_SNORM, 1, 1, 0, GL_RGBA, GL_BYTE, nullptr); break; case TextureType::Float: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT, nullptr); break; case TextureType::UnsignedInteger: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, nullptr); break; case TextureType::SignedInteger: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8I, 1, 1, 0, GL_RGBA_INTEGER, GL_BYTE, nullptr); break; case TextureType::Depth: glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr); break; case TextureType::DepthStencilDepthMode: glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, 1, 1, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, nullptr); break; case TextureType::DepthStencilStencilMode: ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_stencil_texturing")); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, 1, 1, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE_ANGLE, GL_STENCIL_INDEX); break; case TextureType::Stencil: ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_stencil8")); glTexImage2D(GL_TEXTURE_2D, 0, GL_STENCIL_INDEX8, 1, 1, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, nullptr); break; } ASSERT_GL_NO_ERROR(); switch (textureCompareMode) { case TextureCompareMode::None: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); break; case TextureCompareMode::Ref: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); break; } ASSERT_GL_NO_ERROR(); drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f); EXPECT_GL_NO_ERROR(); } constexpr SamplerType kSamplerTypes[] = { SamplerType::Float, SamplerType::SignedInteger, SamplerType::UnsignedInteger, SamplerType::Shadow, }; constexpr TextureType kTextureTypes[] = { TextureType::UnsignedNormalized, TextureType::SignedNormalized, TextureType::Float, TextureType::UnsignedInteger, TextureType::SignedInteger, TextureType::Depth, TextureType::DepthStencilDepthMode, TextureType::DepthStencilStencilMode, TextureType::Stencil, }; constexpr TextureCompareMode kTextureCompareModes[] = { TextureCompareMode::None, TextureCompareMode::Ref, }; GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IncompatibleTextureTest); ANGLE_INSTANTIATE_TEST_COMBINE_3(IncompatibleTextureTest, IncompatibleTextureVariationsTestPrint, testing::ValuesIn(kSamplerTypes), testing::ValuesIn(kTextureTypes), testing::ValuesIn(kTextureCompareModes), ANGLE_ALL_TEST_PLATFORMS_ES3); } // anonymous namespace