mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-07 06:09:57 +03:00
Fix handling of incomplete CubeMapArray textures
GFXBench Car Chase binds a cube map array as a default texture, then immediately samples from it without setting it up. This ends up treating the cube map array as incomplete. On the Vulkan backend, this is resulting in multiple validation errors, followed by a crash in the driver. There are a number of errors, but a telling one is this: vkCreateImage(): pCreateInfo->flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, but pCreateInfo->arrayLayers (=1) is not greater than or equal to 6. The Vulkan spec states: If imageType is VK_IMAGE_TYPE_2D and flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, extent.width and extent.height must be equal and arrayLayers must be greater than or equal to 6 This corresponds to language in the GLES 3.2 spec: 8.18. IMMUTABLE-FORMAT TEXTURE IMAGES TexStorage3D Errors An INVALID_OPERATION error is generated if any of the following conditions hold: * target is TEXTURE_CUBE_MAP_ARRAY and depth is not a multiple of 6 Since ANGLE treats incomplete textures as immutable, we need to update the dimensions of the backing image for CUBE_MAP_ARRAY. Also add a new test that exposes the problem. Test: IncompleteTextureTestES31.IncompleteTextureCubeMapArray Bug: b/218314686 Change-Id: Ibef41e15a7cfccb05e6039bfb8504d237bc42cd4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3546290 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Cody Northrop <cnorthrop@google.com>
This commit is contained in:
committed by
Angle LUCI CQ
parent
041c4c6d28
commit
32af258def
@@ -591,13 +591,27 @@ angle::Result IncompleteTextureSet::getIncompleteTexture(
|
||||
|
||||
ContextImpl *implFactory = context->getImplementation();
|
||||
|
||||
const gl::Extents colorSize(1, 1, 1);
|
||||
gl::Extents colorSize(1, 1, 1);
|
||||
gl::PixelUnpackState unpack;
|
||||
unpack.alignment = 1;
|
||||
const gl::Box area(0, 0, 0, 1, 1, 1);
|
||||
gl::Box area(0, 0, 0, 1, 1, 1);
|
||||
const IncompleteTextureParameters &incompleteTextureParam =
|
||||
kIncompleteTextureParameters[format];
|
||||
|
||||
// Cube map arrays are expected to have layer counts that are multiples of 6
|
||||
constexpr int kCubeMapArraySize = 6;
|
||||
if (type == gl::TextureType::CubeMapArray)
|
||||
{
|
||||
// From the GLES 3.2 spec:
|
||||
// 8.18. IMMUTABLE-FORMAT TEXTURE IMAGES
|
||||
// TexStorage3D Errors
|
||||
// An INVALID_OPERATION error is generated if any of the following conditions hold:
|
||||
// * target is TEXTURE_CUBE_MAP_ARRAY and depth is not a multiple of 6
|
||||
// Since ANGLE treats incomplete textures as immutable, respect that here.
|
||||
colorSize.depth = kCubeMapArraySize;
|
||||
area.depth = kCubeMapArraySize;
|
||||
}
|
||||
|
||||
// If a texture is external use a 2D texture for the incomplete texture
|
||||
gl::TextureType createType = (type == gl::TextureType::External) ? gl::TextureType::_2D : type;
|
||||
|
||||
@@ -638,6 +652,23 @@ angle::Result IncompleteTextureSet::getIncompleteTexture(
|
||||
incompleteTextureParam.clearColor));
|
||||
}
|
||||
}
|
||||
else if (type == gl::TextureType::CubeMapArray)
|
||||
{
|
||||
// We need to provide enough pixel data to fill the array of six faces
|
||||
GLubyte incompleteCubeArrayPixels[kCubeMapArraySize][4];
|
||||
for (int i = 0; i < kCubeMapArraySize; ++i)
|
||||
{
|
||||
incompleteCubeArrayPixels[i][0] = incompleteTextureParam.clearColor[0];
|
||||
incompleteCubeArrayPixels[i][1] = incompleteTextureParam.clearColor[1];
|
||||
incompleteCubeArrayPixels[i][2] = incompleteTextureParam.clearColor[2];
|
||||
incompleteCubeArrayPixels[i][3] = incompleteTextureParam.clearColor[3];
|
||||
}
|
||||
|
||||
ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr,
|
||||
gl::NonCubeTextureTypeToTarget(createType), 0, area,
|
||||
incompleteTextureParam.format, incompleteTextureParam.type,
|
||||
*incompleteCubeArrayPixels));
|
||||
}
|
||||
else if (type == gl::TextureType::_2DMultisample)
|
||||
{
|
||||
// Call a specialized clear function to init a multisample texture.
|
||||
|
||||
@@ -242,6 +242,56 @@ void main()
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
|
||||
}
|
||||
|
||||
// This mirrors a scenario seen in GFXBench Car Chase where a
|
||||
// default CUBE_MAP_ARRAY texture is used without being setup.
|
||||
// Its ends up sampling from an incomplete texture.
|
||||
TEST_P(IncompleteTextureTestES31, IncompleteTextureCubeMapArray)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_cube_map_array"));
|
||||
|
||||
constexpr char kVS[] =
|
||||
R"(#version 310 es
|
||||
precision mediump float;
|
||||
in vec3 pos;
|
||||
void main() {
|
||||
gl_Position = vec4(pos, 1.0);
|
||||
})";
|
||||
|
||||
constexpr char kFS[] =
|
||||
R"(#version 310 es
|
||||
#extension GL_EXT_texture_cube_map_array : enable
|
||||
precision mediump float;
|
||||
out vec4 color;
|
||||
uniform lowp samplerCubeArray uTex;
|
||||
void main(){
|
||||
vec4 outColor = vec4(0.0);
|
||||
|
||||
// Pull a color from each cube face to ensure they are all initialized
|
||||
outColor += texture(uTex, vec4(1.0, 0.0, 0.0, 0.0));
|
||||
outColor += texture(uTex, vec4(-1.0, 0.0, 0.0, 0.0));
|
||||
outColor += texture(uTex, vec4(0.0, 1.0, 0.0, 0.0));
|
||||
outColor += texture(uTex, vec4(0.0, -1.0, 0.0, 0.0));
|
||||
outColor += texture(uTex, vec4(0.0, 0.0, 1.0, 0.0));
|
||||
outColor += texture(uTex, vec4(0.0, 0.0, -1.0, 0.0));
|
||||
|
||||
color = outColor;
|
||||
})";
|
||||
|
||||
ANGLE_GL_PROGRAM(program, kVS, kFS);
|
||||
glUseProgram(program);
|
||||
|
||||
glUniform1i(glGetUniformLocation(program, "uTex"), 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// Bind the default texture and don't set it up. This ends up being incomplete.
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
|
||||
|
||||
drawQuad(program, "pos", 0.5f, 1.0f, true);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::black);
|
||||
}
|
||||
|
||||
// Verifies that an incomplete integer texture has a signed integer type default value.
|
||||
TEST_P(IncompleteTextureTestES3, IntegerType)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user