Commit 7005248b by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fix glCopyTextureCHROMIUM if source is swizzled

A no-swizzle view is added for this use-case. Bug: angleproject:4004 Change-Id: Id654af9a4f520357c91bf2b06501c9e1ea169f11 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2241623Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent e2d64532
......@@ -584,7 +584,7 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
return copySubImageImplWithDraw(
contextVk, offsetImageIndex, destOffset, destVkFormat, sourceLevel, sourceArea, false,
unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha, &source->getImage(),
&source->getFetchImageViewAndRecordUse(contextVk));
&source->getCopyImageViewAndRecordUse(contextVk));
}
if (sourceLevel != 0)
......@@ -1751,6 +1751,20 @@ const vk::ImageView &TextureVk::getFetchImageViewAndRecordUse(ContextVk *context
: mImageViews.getReadImageView());
}
const vk::ImageView &TextureVk::getCopyImageViewAndRecordUse(ContextVk *contextVk) const
{
ASSERT(mImage->valid());
mImageViews.retain(&contextVk->getResourceUseList());
if (mState.getSRGBOverride() == gl::SrgbOverride::Enabled)
{
return mImageViews.getNonLinearCopyImageView();
}
return mImageViews.getCopyImageView();
}
angle::Result TextureVk::getLevelLayerImageView(ContextVk *contextVk,
size_t level,
size_t layer,
......@@ -1819,21 +1833,20 @@ angle::Result TextureVk::initImageViews(ContextVk *contextVk,
{
ASSERT(mImage != nullptr && mImage->valid());
// TODO(cnorthrop): May be missing non-zero base level http://anglebug.com/3948
uint32_t baseLevel = getNativeImageLevel(0);
uint32_t baseLayer = getNativeImageLayer(0);
gl::SwizzleState mappedSwizzle;
MapSwizzleState(contextVk, format, sized, mState.getSwizzleState(), &mappedSwizzle);
gl::SwizzleState formatSwizzle = GetFormatSwizzle(contextVk, format, sized);
gl::SwizzleState readSwizzle = ApplySwizzle(formatSwizzle, mState.getSwizzleState());
ANGLE_TRY(mImageViews.initReadViews(contextVk, mState.getType(), *mImage, format, mappedSwizzle,
baseLevel, levelCount, baseLayer, layerCount));
ANGLE_TRY(mImageViews.initReadViews(contextVk, mState.getType(), *mImage, format, formatSwizzle,
readSwizzle, baseLevel, levelCount, baseLayer, layerCount));
if ((mImageCreateFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) != 0)
{
ANGLE_TRY(mImageViews.initSRGBReadViews(contextVk, mState.getType(), *mImage, format,
mappedSwizzle, baseLevel, levelCount, baseLayer,
layerCount));
formatSwizzle, readSwizzle, baseLevel, levelCount,
baseLayer, layerCount));
}
return angle::Result::Continue;
......
......@@ -175,6 +175,8 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
// A special view for cube maps as a 2D array, used with shaders that do texelFetch() and for
// seamful cube map emulation.
const vk::ImageView &getFetchImageViewAndRecordUse(ContextVk *contextVk) const;
// A special view used for texture copies that shouldn't perform swizzle.
const vk::ImageView &getCopyImageViewAndRecordUse(ContextVk *contextVk) const;
angle::Result getStorageImageView(ContextVk *contextVk,
bool allLayers,
size_t level,
......
......@@ -334,22 +334,22 @@ GLenum GetSwizzleStateComponent(const gl::SwizzleState &swizzleState, GLenum com
}
}
// Places the swizzle obtained by applying second after first into out.
void ComposeSwizzleState(const gl::SwizzleState &first,
const gl::SwizzleState &second,
gl::SwizzleState *out)
gl::SwizzleState ApplySwizzle(const gl::SwizzleState &formatSwizzle,
const gl::SwizzleState &toApply)
{
out->swizzleRed = GetSwizzleStateComponent(first, second.swizzleRed);
out->swizzleGreen = GetSwizzleStateComponent(first, second.swizzleGreen);
out->swizzleBlue = GetSwizzleStateComponent(first, second.swizzleBlue);
out->swizzleAlpha = GetSwizzleStateComponent(first, second.swizzleAlpha);
gl::SwizzleState result;
result.swizzleRed = GetSwizzleStateComponent(formatSwizzle, toApply.swizzleRed);
result.swizzleGreen = GetSwizzleStateComponent(formatSwizzle, toApply.swizzleGreen);
result.swizzleBlue = GetSwizzleStateComponent(formatSwizzle, toApply.swizzleBlue);
result.swizzleAlpha = GetSwizzleStateComponent(formatSwizzle, toApply.swizzleAlpha);
return result;
}
void MapSwizzleState(const ContextVk *contextVk,
gl::SwizzleState GetFormatSwizzle(const ContextVk *contextVk,
const vk::Format &format,
const bool sized,
const gl::SwizzleState &swizzleState,
gl::SwizzleState *swizzleStateOut)
const bool sized)
{
const angle::Format &angleFormat = format.intendedFormat();
......@@ -401,6 +401,7 @@ void MapSwizzleState(const ContextVk *contextVk,
}
}
}
ComposeSwizzleState(internalSwizzle, swizzleState, swizzleStateOut);
return internalSwizzle;
}
} // namespace rx
......@@ -163,11 +163,14 @@ bool HasNonRenderableTextureFormatSupport(RendererVk *renderer, VkFormat vkForma
// calculation is listed in the Vulkan spec at the end of the section 'Vertex Input Description'.
size_t GetVertexInputAlignment(const vk::Format &format);
void MapSwizzleState(const ContextVk *contextVk,
// Get the swizzle state based on format's requirements and emulations.
gl::SwizzleState GetFormatSwizzle(const ContextVk *contextVk,
const vk::Format &format,
const bool sized,
const gl::SwizzleState &swizzleState,
gl::SwizzleState *swizzleStateOut);
const bool sized);
// Apply application's swizzle to the swizzle implied by format as received from GetFormatSwizzle.
gl::SwizzleState ApplySwizzle(const gl::SwizzleState &formatSwizzle,
const gl::SwizzleState &toApply);
namespace vk
{
......
......@@ -4584,6 +4584,8 @@ ImageViewHelper::ImageViewHelper(ImageViewHelper &&other)
std::swap(mNonLinearReadImageView, other.mNonLinearReadImageView);
std::swap(mLinearFetchImageView, other.mLinearFetchImageView);
std::swap(mNonLinearFetchImageView, other.mNonLinearFetchImageView);
std::swap(mLinearCopyImageView, other.mLinearCopyImageView);
std::swap(mNonLinearCopyImageView, other.mNonLinearCopyImageView);
std::swap(mLinearColorspace, other.mLinearColorspace);
std::swap(mStencilReadImageView, other.mStencilReadImageView);
......@@ -4616,6 +4618,14 @@ void ImageViewHelper::release(RendererVk *renderer)
{
garbage.emplace_back(GetGarbage(&mNonLinearFetchImageView));
}
if (mLinearCopyImageView.valid())
{
garbage.emplace_back(GetGarbage(&mLinearCopyImageView));
}
if (mNonLinearCopyImageView.valid())
{
garbage.emplace_back(GetGarbage(&mNonLinearCopyImageView));
}
if (mStencilReadImageView.valid())
{
garbage.emplace_back(GetGarbage(&mStencilReadImageView));
......@@ -4657,6 +4667,8 @@ void ImageViewHelper::destroy(VkDevice device)
mNonLinearReadImageView.destroy(device);
mLinearFetchImageView.destroy(device);
mNonLinearFetchImageView.destroy(device);
mLinearCopyImageView.destroy(device);
mNonLinearCopyImageView.destroy(device);
mStencilReadImageView.destroy(device);
for (ImageView &imageView : mLevelDrawImageViews)
......@@ -4679,7 +4691,8 @@ angle::Result ImageViewHelper::initReadViews(ContextVk *contextVk,
gl::TextureType viewType,
const ImageHelper &image,
const Format &format,
const gl::SwizzleState &swizzleState,
const gl::SwizzleState &formatSwizzle,
const gl::SwizzleState &readSwizzle,
uint32_t baseLevel,
uint32_t levelCount,
uint32_t baseLayer,
......@@ -4691,30 +4704,35 @@ angle::Result ImageViewHelper::initReadViews(ContextVk *contextVk,
if (HasBothDepthAndStencilAspects(aspectFlags))
{
ANGLE_TRY(image.initLayerImageView(contextVk, viewType, VK_IMAGE_ASPECT_DEPTH_BIT,
swizzleState, &getReadImageView(), baseLevel, levelCount,
readSwizzle, &getReadImageView(), baseLevel, levelCount,
baseLayer, layerCount));
ANGLE_TRY(image.initLayerImageView(contextVk, viewType, VK_IMAGE_ASPECT_STENCIL_BIT,
swizzleState, &mStencilReadImageView, baseLevel,
readSwizzle, &mStencilReadImageView, baseLevel,
levelCount, baseLayer, layerCount));
}
else
{
ANGLE_TRY(image.initLayerImageView(contextVk, viewType, aspectFlags, swizzleState,
ANGLE_TRY(image.initLayerImageView(contextVk, viewType, aspectFlags, readSwizzle,
&getReadImageView(), baseLevel, levelCount, baseLayer,
layerCount));
}
gl::TextureType fetchType = viewType;
if (viewType == gl::TextureType::CubeMap || viewType == gl::TextureType::_2DArray ||
viewType == gl::TextureType::_2DMultisampleArray)
{
gl::TextureType arrayType = Get2DTextureType(layerCount, image.getSamples());
fetchType = Get2DTextureType(layerCount, image.getSamples());
// TODO(http://anglebug.com/4004): SwizzleState incorrect for CopyTextureCHROMIUM.
ANGLE_TRY(image.initLayerImageView(contextVk, arrayType, aspectFlags, swizzleState,
ANGLE_TRY(image.initLayerImageView(contextVk, fetchType, aspectFlags, readSwizzle,
&getFetchImageView(), baseLevel, levelCount, baseLayer,
layerCount));
}
ANGLE_TRY(image.initLayerImageView(contextVk, fetchType, aspectFlags, formatSwizzle,
&getCopyImageView(), baseLevel, levelCount, baseLayer,
layerCount));
return angle::Result::Continue;
}
......@@ -4722,7 +4740,8 @@ angle::Result ImageViewHelper::initSRGBReadViews(ContextVk *contextVk,
gl::TextureType viewType,
const ImageHelper &image,
const Format &format,
const gl::SwizzleState &swizzleState,
const gl::SwizzleState &formatSwizzle,
const gl::SwizzleState &readSwizzle,
uint32_t baseLevel,
uint32_t levelCount,
uint32_t baseLayer,
......@@ -4738,38 +4757,52 @@ angle::Result ImageViewHelper::initSRGBReadViews(ContextVk *contextVk,
if (!mLinearReadImageView.valid())
{
ANGLE_TRY(image.initLayerImageViewImpl(contextVk, viewType, aspectFlags, swizzleState,
ANGLE_TRY(image.initLayerImageViewImpl(contextVk, viewType, aspectFlags, readSwizzle,
&mLinearReadImageView, baseLevel, levelCount,
baseLayer, layerCount, linearFormat));
}
if (nonLinearOverrideFormat != VK_FORMAT_UNDEFINED && !mNonLinearReadImageView.valid())
{
ANGLE_TRY(image.initLayerImageViewImpl(contextVk, viewType, aspectFlags, swizzleState,
ANGLE_TRY(image.initLayerImageViewImpl(contextVk, viewType, aspectFlags, readSwizzle,
&mNonLinearReadImageView, baseLevel, levelCount,
baseLayer, layerCount, nonLinearOverrideFormat));
}
gl::TextureType fetchType = viewType;
if (viewType == gl::TextureType::CubeMap || viewType == gl::TextureType::_2DArray ||
viewType == gl::TextureType::_2DMultisampleArray)
{
gl::TextureType arrayType = Get2DTextureType(layerCount, image.getSamples());
fetchType = Get2DTextureType(layerCount, image.getSamples());
// TODO(http://anglebug.com/4004): SwizzleState incorrect for CopyTextureCHROMIUM.
if (!mLinearFetchImageView.valid())
{
ANGLE_TRY(image.initLayerImageViewImpl(contextVk, arrayType, aspectFlags, swizzleState,
ANGLE_TRY(image.initLayerImageViewImpl(contextVk, fetchType, aspectFlags, readSwizzle,
&mLinearFetchImageView, baseLevel, levelCount,
baseLayer, layerCount, linearFormat));
}
if (nonLinearOverrideFormat != VK_FORMAT_UNDEFINED && !mNonLinearFetchImageView.valid())
{
ANGLE_TRY(image.initLayerImageViewImpl(contextVk, viewType, aspectFlags, swizzleState,
ANGLE_TRY(image.initLayerImageViewImpl(contextVk, fetchType, aspectFlags, readSwizzle,
&mNonLinearFetchImageView, baseLevel, levelCount,
baseLayer, layerCount, nonLinearOverrideFormat));
}
}
if (!mLinearCopyImageView.valid())
{
ANGLE_TRY(image.initLayerImageViewImpl(contextVk, fetchType, aspectFlags, formatSwizzle,
&mLinearCopyImageView, baseLevel, levelCount,
baseLayer, layerCount, linearFormat));
}
if (nonLinearOverrideFormat != VK_FORMAT_UNDEFINED && !mNonLinearCopyImageView.valid())
{
ANGLE_TRY(image.initLayerImageViewImpl(contextVk, fetchType, aspectFlags, formatSwizzle,
&mNonLinearCopyImageView, baseLevel, levelCount,
baseLayer, layerCount, nonLinearOverrideFormat));
}
return angle::Result::Continue;
}
......
......@@ -1519,6 +1519,8 @@ class ImageViewHelper : angle::NonCopyable
const ImageView &getNonLinearReadImageView() const { return mNonLinearReadImageView; }
const ImageView &getLinearFetchImageView() const { return mLinearFetchImageView; }
const ImageView &getNonLinearFetchImageView() const { return mNonLinearFetchImageView; }
const ImageView &getLinearCopyImageView() const { return mLinearCopyImageView; }
const ImageView &getNonLinearCopyImageView() const { return mNonLinearCopyImageView; }
const ImageView &getStencilReadImageView() const { return mStencilReadImageView; }
const ImageView &getReadImageView() const
......@@ -1531,6 +1533,11 @@ class ImageViewHelper : angle::NonCopyable
return mLinearColorspace ? mLinearFetchImageView : mNonLinearFetchImageView;
}
const ImageView &getCopyImageView() const
{
return mLinearColorspace ? mLinearCopyImageView : mNonLinearCopyImageView;
}
// Used when initialized RenderTargets.
bool hasStencilReadImageView() const { return mStencilReadImageView.valid(); }
......@@ -1544,7 +1551,8 @@ class ImageViewHelper : angle::NonCopyable
gl::TextureType viewType,
const ImageHelper &image,
const Format &format,
const gl::SwizzleState &swizzleState,
const gl::SwizzleState &formatSwizzle,
const gl::SwizzleState &readSwizzle,
uint32_t baseLevel,
uint32_t levelCount,
uint32_t baseLayer,
......@@ -1555,7 +1563,8 @@ class ImageViewHelper : angle::NonCopyable
gl::TextureType viewType,
const ImageHelper &image,
const Format &format,
const gl::SwizzleState &swizzleState,
const gl::SwizzleState &formatSwizzle,
const gl::SwizzleState &readSwizzle,
uint32_t baseLevel,
uint32_t levelCount,
uint32_t baseLayer,
......@@ -1585,6 +1594,10 @@ class ImageViewHelper : angle::NonCopyable
{
return mLinearColorspace ? mLinearFetchImageView : mNonLinearFetchImageView;
}
ImageView &getCopyImageView()
{
return mLinearColorspace ? mLinearCopyImageView : mNonLinearCopyImageView;
}
// Lifetime.
SharedResourceUse mUse;
......@@ -1594,6 +1607,8 @@ class ImageViewHelper : angle::NonCopyable
ImageView mNonLinearReadImageView;
ImageView mLinearFetchImageView;
ImageView mNonLinearFetchImageView;
ImageView mLinearCopyImageView;
ImageView mNonLinearCopyImageView;
ImageView mStencilReadImageView;
bool mLinearColorspace;
......
......@@ -2300,6 +2300,50 @@ TEST_P(CopyTextureTestES3, CopyBetweenMips)
EXPECT_PIXEL_COLOR_EQ(w, h, kMip0InitColor[4 * 0 + 2]);
}
// Test that swizzle on source texture does not affect the copy.
TEST_P(CopyTextureTestES3, SwizzleOnSource)
{
const GLColor kSourceColor = GLColor(31, 73, 146, 228);
// Create image with swizzle. If swizzle is mistakenly applied, resulting color would be
// kSourceColor.gbar
GLTexture sourceTexture;
glBindTexture(GL_TEXTURE_2D, sourceTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kSourceColor);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_GREEN);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ALPHA);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
GLTexture destTexture;
glBindTexture(GL_TEXTURE_2D, destTexture);
// Note: flipY is used to avoid direct transfer between textures and force a draw-based path.
glCopyTextureCHROMIUM(sourceTexture, 0, GL_TEXTURE_2D, destTexture, 0, GL_RGBA8,
GL_UNSIGNED_BYTE, true, false, false);
ASSERT_GL_NO_ERROR();
// Verify the copy.
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
glUseProgram(program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, destTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLint textureLocation = glGetUniformLocation(program, essl1_shaders::Texture2DUniform());
ASSERT_NE(-1, textureLocation);
glUniform1i(textureLocation, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, kSourceColor);
}
#ifdef Bool
// X11 craziness.
# undef Bool
......
......@@ -2431,7 +2431,7 @@ TEST_P(Texture2DTestES3, TextureImplPropogatesDirtyBits)
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
// D3D Debug device reports an error. http://anglebug.com/3501
ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());
// TODO(cnorthrop): Needs triage on Vulkan backend. http://anglebug.com/3950
// Support copy from levels outside the image range. http://anglebug.com/4733
ANGLE_SKIP_TEST_IF(IsVulkan());
// The workaround in the GL backend required to trigger this bug generates driver warning
......
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