Commit 26a54260 by Mohan Maiya Committed by Angle LUCI CQ

Reland "Vulkan: Handle immutable sampler state change in TextureVk"

This is a reland of 349c0830 Skip YUV tests on Pixel2 Original change's description: > Vulkan: Handle immutable sampler state change in TextureVk > > Transitioning between sources in RGB and YUV colorspace or between > YUV formats with different layout should force the recreation of > pipeline layout and the invalidation of texture's sampler. > > Only textures that are EGLImage targets are handled for now. > > Bug: b/155487768 > Bug: angleproject:5033 > Bug: angleproject:5773 > Test: ImageTest.SourceAHBTarget2DExternalCycleThrough*Vulkan > Change-Id: I02d5763e7f89b910313e14b57bfc5403113dfbb2 > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2924415 > Reviewed-by: Jamie Madill <jmadill@chromium.org> > Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> > Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Bug: b/155487768 Bug: angleproject:5033 Bug: angleproject:5773 Change-Id: Ie3791bc6f6e9b53eb0db23759a14fdc038c8f5b6 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2939354 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 03d8e7c9
...@@ -4820,7 +4820,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -4820,7 +4820,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask(); const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes(); const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
bool haveImmutableSampler = false; bool recreatePipelineLayout = false;
for (size_t textureUnit : activeTextures) for (size_t textureUnit : activeTextures)
{ {
gl::Texture *texture = textures[textureUnit]; gl::Texture *texture = textures[textureUnit];
...@@ -4898,16 +4898,13 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -4898,16 +4898,13 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
textureVk->getImageViewSubresourceSerial(samplerState); textureVk->getImageViewSubresourceSerial(samplerState);
mActiveTexturesDesc.update(textureUnit, imageViewSerial, samplerHelper.getSamplerSerial()); mActiveTexturesDesc.update(textureUnit, imageViewSerial, samplerHelper.getSamplerSerial());
if (textureVk->getImage().hasImmutableSampler()) recreatePipelineLayout =
{ textureVk->getAndResetImmutableSamplerDirtyState() || recreatePipelineLayout;
haveImmutableSampler = true;
}
} }
if (haveImmutableSampler) // Recreate the pipeline layout, if necessary.
if (recreatePipelineLayout)
{ {
// TODO(http://anglebug.com/5033): This will recreate the descriptor pools each time, which
// will likely affect performance negatively.
ANGLE_TRY(mExecutable->createPipelineLayout(context, &mActiveTextures)); ANGLE_TRY(mExecutable->createPipelineLayout(context, &mActiveTextures));
// The default uniforms descriptor set was reset during createPipelineLayout(), so mark them // The default uniforms descriptor set was reset during createPipelineLayout(), so mark them
......
...@@ -269,6 +269,7 @@ TextureVk::TextureVk(const gl::TextureState &state, RendererVk *renderer) ...@@ -269,6 +269,7 @@ TextureVk::TextureVk(const gl::TextureState &state, RendererVk *renderer)
: TextureImpl(state), : TextureImpl(state),
mOwnsImage(false), mOwnsImage(false),
mRequiresMutableStorage(false), mRequiresMutableStorage(false),
mImmutableSamplerDirty(false),
mImageNativeType(gl::TextureType::InvalidEnum), mImageNativeType(gl::TextureType::InvalidEnum),
mImageLayerOffset(0), mImageLayerOffset(0),
mImageLevelOffset(0), mImageLevelOffset(0),
...@@ -1289,18 +1290,50 @@ angle::Result TextureVk::setStorageExternalMemory(const gl::Context *context, ...@@ -1289,18 +1290,50 @@ angle::Result TextureVk::setStorageExternalMemory(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
void TextureVk::handleImmutableSamplerTransition(const vk::ImageHelper *previousImage,
const vk::ImageHelper *nextImage)
{
// Did the previous image have an immutable sampler
bool previousImageHadImmutableSampler =
previousImage && previousImage->valid() && previousImage->hasImmutableSampler();
// Does the next image require an immutable sampler?
bool nextImageRequiresImmutableSampler =
nextImage && nextImage->valid() && nextImage->hasImmutableSampler();
// Has the external format changed?
bool externalFormatChanged = false;
if (previousImageHadImmutableSampler && nextImageRequiresImmutableSampler)
{
externalFormatChanged =
previousImage->getExternalFormat() != nextImage->getExternalFormat();
}
// Handle transition of immutable sampler state
if ((previousImageHadImmutableSampler != nextImageRequiresImmutableSampler) ||
externalFormatChanged)
{
// The immutable sampler state is dirty.
mSampler.reset();
mImmutableSamplerDirty = true;
}
}
angle::Result TextureVk::setEGLImageTarget(const gl::Context *context, angle::Result TextureVk::setEGLImageTarget(const gl::Context *context,
gl::TextureType type, gl::TextureType type,
egl::Image *image) egl::Image *image)
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
ImageVk *imageVk = vk::GetImpl(image);
// TODO: Textures other than EGLImage targets can have immutable samplers.
// http://anglebug.com/5773
handleImmutableSamplerTransition(mImage, (imageVk) ? imageVk->getImage() : nullptr);
releaseAndDeleteImageAndViews(contextVk); releaseAndDeleteImageAndViews(contextVk);
const vk::Format &format = renderer->getFormat(image->getFormat().info->sizedInternalFormat); const vk::Format &format = renderer->getFormat(image->getFormat().info->sizedInternalFormat);
ImageVk *imageVk = vk::GetImpl(image);
setImageHelper(contextVk, imageVk->getImage(), imageVk->getImageTextureType(), format, setImageHelper(contextVk, imageVk->getImage(), imageVk->getImageTextureType(), format,
imageVk->getImageLevel().get(), imageVk->getImageLayer(), imageVk->getImageLevel().get(), imageVk->getImageLayer(),
gl::LevelIndex(mState.getEffectiveBaseLevel()), false); gl::LevelIndex(mState.getEffectiveBaseLevel()), false);
......
...@@ -273,6 +273,13 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -273,6 +273,13 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
angle::Result ensureMutable(ContextVk *contextVk); angle::Result ensureMutable(ContextVk *contextVk);
bool getAndResetImmutableSamplerDirtyState()
{
bool isDirty = mImmutableSamplerDirty;
mImmutableSamplerDirty = false;
return isDirty;
}
private: private:
// Transform an image index from the frontend into one that can be used on the backing // Transform an image index from the frontend into one that can be used on the backing
// ImageHelper, taking into account mipmap or cube face offsets // ImageHelper, taking into account mipmap or cube face offsets
...@@ -469,9 +476,12 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -469,9 +476,12 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
angle::Result refreshImageViews(ContextVk *contextVk); angle::Result refreshImageViews(ContextVk *contextVk);
bool shouldDecodeSRGB(ContextVk *contextVk, GLenum srgbDecode, bool texelFetchStaticUse) const; bool shouldDecodeSRGB(ContextVk *contextVk, GLenum srgbDecode, bool texelFetchStaticUse) const;
void initImageUsageFlags(ContextVk *contextVk, const vk::Format &format); void initImageUsageFlags(ContextVk *contextVk, const vk::Format &format);
void handleImmutableSamplerTransition(const vk::ImageHelper *previousImage,
const vk::ImageHelper *nextImage);
bool mOwnsImage; bool mOwnsImage;
bool mRequiresMutableStorage; bool mRequiresMutableStorage;
bool mImmutableSamplerDirty;
gl::TextureType mImageNativeType; gl::TextureType mImageNativeType;
......
...@@ -1871,7 +1871,7 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1871,7 +1871,7 @@ class ImageHelper final : public Resource, public angle::Subject
uint32_t layerStart, uint32_t layerStart,
uint32_t layerCount, uint32_t layerCount,
VkImageAspectFlags aspectFlags); VkImageAspectFlags aspectFlags);
bool hasImmutableSampler() { return mExternalFormat != 0; } bool hasImmutableSampler() const { return mExternalFormat != 0; }
uint64_t getExternalFormat() const { return mExternalFormat; } uint64_t getExternalFormat() const { return mExternalFormat; }
// Used by framebuffer and render pass functions to decide loadOps and invalidate/un-invalidate // Used by framebuffer and render pass functions to decide loadOps and invalidate/un-invalidate
......
...@@ -93,9 +93,11 @@ GLubyte kSrgbColorCube[] = {18, 62, 155, 255, 149, 26, 60, 255, 41, 149, 38, ...@@ -93,9 +93,11 @@ GLubyte kSrgbColorCube[] = {18, 62, 155, 255, 149, 26, 60, 255, 41, 149, 38,
3, 26, 202, 255, 117, 164, 16, 255, 19, 41, 32, 255}; 3, 26, 202, 255, 117, 164, 16, 255, 19, 41, 32, 255};
constexpr int kColorspaceAttributeIndex = 2; constexpr int kColorspaceAttributeIndex = 2;
constexpr int AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1; constexpr int AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1;
constexpr int AHARDWAREBUFFER_FORMAT_D24_UNORM = 0x31; constexpr int AHARDWAREBUFFER_FORMAT_D24_UNORM = 0x31;
constexpr int AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23; constexpr int AHARDWAREBUFFER_FORMAT_Y8Cr8Cb8_420_SP = 0x11;
constexpr int AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23;
constexpr int AHARDWAREBUFFER_FORMAT_YV12 = 0x32315659;
} // anonymous namespace } // anonymous namespace
...@@ -1878,6 +1880,154 @@ void ImageTest::SourceAHBTarget2D_helper(const EGLint *attribs) ...@@ -1878,6 +1880,154 @@ void ImageTest::SourceAHBTarget2D_helper(const EGLint *attribs)
glDeleteTextures(1, &target); glDeleteTextures(1, &target);
} }
// Testing source AHB EGL images, target 2D external texture, cycling through YUV sources.
TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughYuvSourcesNoData)
{
// http://issuetracker.google.com/175021871
ANGLE_SKIP_TEST_IF(IsPixel2() || IsPixel2XL());
ANGLE_SKIP_TEST_IF(!IsAndroid());
EGLWindow *window = getEGLWindow();
ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
// Create YCbCr source and image but without initial data
AHardwareBuffer *ycbcrSource;
EGLImageKHR ycbcrImage;
createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420,
kDefaultAttribs, {}, &ycbcrSource, &ycbcrImage);
EXPECT_NE(ycbcrSource, nullptr);
EXPECT_NE(ycbcrImage, EGL_NO_IMAGE_KHR);
// Create YCrCb source and image but without initial data
AHardwareBuffer *ycrcbSource;
EGLImageKHR ycrcbImage;
createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cr8Cb8_420_SP,
kDefaultAttribs, {}, &ycrcbSource, &ycrcbImage);
EXPECT_NE(ycrcbSource, nullptr);
EXPECT_NE(ycrcbImage, EGL_NO_IMAGE_KHR);
// Create YV12 source and image but without initial data
AHardwareBuffer *yv12Source;
EGLImageKHR yv12Image;
createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_YV12, kDefaultAttribs,
{}, &yv12Source, &yv12Image);
EXPECT_NE(yv12Source, nullptr);
EXPECT_NE(yv12Image, 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 image
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, ycbcrImage);
// 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 YCrCb image
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, ycrcbImage);
// 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 YV12 image
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yv12Image);
// 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(), ycbcrImage);
destroyAndroidHardwareBuffer(ycbcrSource);
eglDestroyImageKHR(window->getDisplay(), ycrcbImage);
destroyAndroidHardwareBuffer(ycrcbSource);
eglDestroyImageKHR(window->getDisplay(), yv12Image);
destroyAndroidHardwareBuffer(yv12Source);
}
// Testing source AHB EGL images, target 2D external texture, cycling through RGB and YUV sources.
TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughRgbAndYuvSources)
{
// http://issuetracker.google.com/175021871
ANGLE_SKIP_TEST_IF(IsPixel2() || IsPixel2XL());
ANGLE_SKIP_TEST_IF(!IsAndroid());
EGLWindow *window = getEGLWindow();
ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
// Create RGB Image
GLubyte rgbColor[4] = {0, 0, 255, 255};
AHardwareBuffer *rgbSource;
EGLImageKHR rgbImage;
createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
kDefaultAttribs, {{rgbColor, 4}}, &rgbSource,
&rgbImage);
// Create YUV Image
// 3 planes of data
GLubyte dataY[4] = {40, 40, 40, 40};
GLubyte dataCb[1] = {
240,
};
GLubyte dataCr[1] = {
109,
};
GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
AHardwareBuffer *yuvSource;
EGLImageKHR yuvImage;
createEGLImageAndroidHardwareBufferSource(
2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAttribs,
{{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &yuvSource, &yuvImage);
// 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 YUV image
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yuvImage);
// Expect render target to have the same color as expectedRgbColor
verifyResultsExternal(target, expectedRgbColor);
// Bind RGB image
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, rgbImage);
// Expect render target to have the same color as rgbColor
verifyResultsExternal(target, rgbColor);
// Bind YUV image
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yuvImage);
// Expect render target to have the same color as expectedRgbColor
verifyResultsExternal(target, expectedRgbColor);
// Clean up
eglDestroyImageKHR(window->getDisplay(), yuvImage);
destroyAndroidHardwareBuffer(yuvSource);
eglDestroyImageKHR(window->getDisplay(), rgbImage);
destroyAndroidHardwareBuffer(rgbSource);
}
// Testing source AHB EGL image, target 2D texture retaining initial data. // Testing source AHB EGL image, target 2D texture retaining initial data.
TEST_P(ImageTest, SourceAHBTarget2DRetainInitialData) TEST_P(ImageTest, SourceAHBTarget2DRetainInitialData)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment