Vulkan: Invalidate sampler if any YCbCr parameter changes Even if the external format stays the same, other parameters like dataspace format may change, and this also requires a new pipeline layout to be created. Bug: b/491850591 Test: Google Meet Test: dEQP-GL* Test: dEQP-EGL* Change-Id: Iec3df8379ecc8aebd0ce0e49cfcf5c87baa54612 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7702372 Reviewed-by: Cody Northrop <cnorthrop@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp index e0aacab..3de8b87 100644 --- a/src/libANGLE/renderer/vulkan/TextureVk.cpp +++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -2348,17 +2348,17 @@ bool nextImageRequiresImmutableSampler = nextImage && nextImage->valid() && nextImage->hasImmutableSampler(); - // Has the external format changed? - bool externalFormatChanged = false; + // Have the YCbCr conversion parameters changed? + bool ycbcrConversionChanged = false; if (previousImageHadImmutableSampler && nextImageRequiresImmutableSampler) { - externalFormatChanged = - previousImage->getExternalFormat() != nextImage->getExternalFormat(); + ycbcrConversionChanged = + previousImage->getYcbcrConversionDesc() != nextImage->getYcbcrConversionDesc(); } // Handle transition of immutable sampler state if ((previousImageHadImmutableSampler != nextImageRequiresImmutableSampler) || - externalFormatChanged) + ycbcrConversionChanged) { // The immutable sampler state is dirty. resetSampler();
diff --git a/src/tests/gl_tests/ImageTest.cpp b/src/tests/gl_tests/ImageTest.cpp index 5f610f5..411bb51 100644 --- a/src/tests/gl_tests/ImageTest.cpp +++ b/src/tests/gl_tests/ImageTest.cpp
@@ -3751,6 +3751,70 @@ destroyAndroidHardwareBuffer(yv12Source); } +// Testing source AHB EGL images, target 2D external texture, cycling through YUV dataspaces. +TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughYuvDataspacesNoData) +{ + EGLWindow *window = getEGLWindow(); + + ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt()); + ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport()); + + // Create YCbCr BT601 source and image but without initial data + AHardwareBuffer *ycbcrBT601Source; + EGLImageKHR ycbcrBT601Image; + createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, + kDefaultAHBYUVUsage, kDefaultAttribs, {}, + &ycbcrBT601Source, &ycbcrBT601Image); + EXPECT_NE(ycbcrBT601Source, nullptr); + EXPECT_NE(ycbcrBT601Image, EGL_NO_IMAGE_KHR); + + // Create YCbCr BT709 source and image but without initial data + // + // There is no API for creating an AHB with a specific dataspace, but Android[1] specifies + // that YCbCr buffers smaller than 720p may be assumed to be BT601, while buffers at least + // 720p may be assumed to be BT709. So we create a 720p image and hope the gralloc + // implementation will pick the correct dataspace. + // + // [1] hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl + AHardwareBuffer *ycbcrBT709Source; + EGLImageKHR ycbcrBT709Image; + createEGLImageAndroidHardwareBufferSource(1280, 720, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, + kDefaultAHBYUVUsage, kDefaultAttribs, {}, + &ycbcrBT709Source, &ycbcrBT709Image); + EXPECT_NE(ycbcrBT709Source, nullptr); + EXPECT_NE(ycbcrBT709Image, EGL_NO_IMAGE_KHR); + + // Create a texture target to bind the egl image + GLTexture target; + glBindTexture(GL_TEXTURE_EXTERNAL_OES, target); + // Disable mipmapping + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + ASSERT_GL_NO_ERROR(); + + // Bind YCbCr BT601 image + glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, ycbcrBT601Image); + // Draw while sampling should result in no EGL/GL errors + glUseProgram(mTextureExternalProgram); + glUniform1i(mTextureExternalUniformLocation, 0); + drawQuad(mTextureExternalProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); + + // Bind YCbCr BT709 image + glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, ycbcrBT709Image); + // Draw while sampling should result in no EGL/GL errors + glUseProgram(mTextureExternalProgram); + glUniform1i(mTextureExternalUniformLocation, 0); + drawQuad(mTextureExternalProgram, "position", 0.5f); + ASSERT_GL_NO_ERROR(); + + // Clean up + eglDestroyImageKHR(window->getDisplay(), ycbcrBT601Image); + destroyAndroidHardwareBuffer(ycbcrBT601Source); + eglDestroyImageKHR(window->getDisplay(), ycbcrBT709Image); + destroyAndroidHardwareBuffer(ycbcrBT709Source); +} + // Testing source AHB EGL images, target 2D external texture, cycling through RGB and YUV sources. TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughRgbAndYuvSources) {