Commit b900f4e2 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Use GPU path for copy to sRGB textures

To avoid creating aliasing views for sRGB textures, the ImageCopy texture will do/undo sRGB transformation such that the final result is as-if both source and destination views were linear. Possible future optimizations: - If either of source or destination has already been created with the MUTABLE flag, i.e. has a linear view already available, that can be used. - If destination is sRGB but not renderable while its corresponding linear format is, and if the image is already created with the MUTABLE flag, using the linear view would allow the copy to go through the GPU instead of the CPU. Bug: b/157934810 Bug: angleproject:4092 Change-Id: I43aaf882c90e1c60d0d9eb04636c203fc04090a4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2241622Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarAntonio Maiorano <amaiorano@google.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent ce29916b
......@@ -164,41 +164,41 @@
"src/libANGLE/renderer/vulkan/shaders/gen/ImageClear.frag.00000017.inc":
"412ac2985b133eabad60c60f85348a60",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000000.inc":
"89c11acedcadb2abd75b68e4b7434f6b",
"9f8b96b844a7116c3e45640e7acc21a4",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000001.inc":
"cf4e3900d0475bd103f1f50bdbe59386",
"238308e0fc29966d6222d8de6fce9f0b",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000002.inc":
"a6f611cd4f233dbea903d23a8a4c00e5",
"8c13eeced676451ef8a3e3ad2a9ab442",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000003.inc":
"614e9f4bfb9f5f867e77176631b615f6",
"2201380521a799c7bbce4d6fd080fa57",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000004.inc":
"9fdd2217cb59b7581eeb623f66c59f74",
"6804b2a2dd9687c1a7767bd272ff6713",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000005.inc":
"8b48341e56f306a56c623f7f3b4b91d2",
"76a6663eb28ebd12f94a1ba0c85fa685",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000008.inc":
"143aef975f75b52d7e5760d3ab316527",
"812de8d46a7f148dc0a3e79866dfc014",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000009.inc":
"0e57e5491fb6fe852dfededfa4e5219a",
"e0fc7b89e5a02334c6bb5797a3a0cb0e",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.0000000A.inc":
"8d9a53b1f3e6f562b64a2a242d4fe842",
"8e24ff2f5567724ad1b44133f7e176f9",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.0000000B.inc":
"b17b91c28f327b699a09869eab24fe8e",
"7eae9f9510a5b718a9dc27d25525b472",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.0000000C.inc":
"cc72bd144deaefdc6910bcf376904e45",
"2f17e13dcae16e671ef3b1999092f87c",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.0000000D.inc":
"25b5791f5758b25554037470fed91be5",
"de095928dff56229991d99178662c5ac",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000010.inc":
"e6382690e91f0f0a6f4cf26979c9be7b",
"1c7457d47e0cc9b138878e2b6ea5d66a",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000011.inc":
"c5fc63e0f66b3b3ca9d72f3dac5e357b",
"0a5f833e77f9359361cf88b070f2c3c3",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000012.inc":
"14f3ed698af8de0798f34538f77dd511",
"22fff94fee349f85bed5f7b88a6e9525",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000013.inc":
"d2b28a2afdccced45f9f2555b46a28ab",
"1ca10b29ac749cfef9fcc71c1ed15178",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000014.inc":
"c52f7073f25b560974f213d8a42d33b8",
"147770b8d926602a70d9bb44b9b6d70e",
"src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000015.inc":
"a4fd26a37f36c287fe3523c2e895ec67",
"9c8b20d4f007d0a268f25eb498d0d935",
"src/libANGLE/renderer/vulkan/shaders/gen/OverlayCull.comp.00000000.inc":
"2c896a8346efa374e247602decd442db",
"src/libANGLE/renderer/vulkan/shaders/gen/OverlayCull.comp.00000001.inc":
......@@ -250,9 +250,9 @@
"src/libANGLE/renderer/vulkan/shaders/src/ImageClear.frag.json":
"f3e0afbc2368002e8a1148edcbe709fa",
"src/libANGLE/renderer/vulkan/shaders/src/ImageCopy.frag":
"e62eb8ee0f264434330382cb2e050a52",
"5c283ab18acb54c2d236f6695086149c",
"src/libANGLE/renderer/vulkan/shaders/src/ImageCopy.frag.json":
"4db849cdf6c706bd8dc827d31dffe04f",
"55b1796c39747ae79ac73159c1750eba",
"src/libANGLE/renderer/vulkan/shaders/src/OverlayCull.comp":
"c89a0d185f7723e0c221c135aa4f48a3",
"src/libANGLE/renderer/vulkan/shaders/src/OverlayCull.comp.json":
......
......@@ -601,8 +601,7 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
sourceLevel, 0, sourceArea, &source->getImage());
}
bool forceCPUPath =
(destFormat.colorEncoding == GL_SRGB) || ForceCPUPathForCopy(renderer, *mImage);
bool forceCPUPath = ForceCPUPathForCopy(renderer, *mImage);
// If it's possible to perform the copy with a draw call, do that.
if (CanCopyWithDraw(renderer, sourceVkFormat, srcTilingMode, destVkFormat, destTilingMode) &&
......
......@@ -1645,6 +1645,20 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
shaderParams.destOffset[0] = params.destOffset[0];
shaderParams.destOffset[1] = params.destOffset[1];
shaderParams.srcIsSRGB =
gl::GetSizedInternalFormatInfo(srcFormat.internalFormat).colorEncoding == GL_SRGB;
shaderParams.destIsSRGB =
gl::GetSizedInternalFormatInfo(dstFormat.internalFormat).colorEncoding == GL_SRGB;
// If both src and dest are sRGB, and there is no alpha multiplication/division necessary, then
// the shader can work with sRGB data and pretend they are linear.
if (shaderParams.srcIsSRGB && shaderParams.destIsSRGB && !shaderParams.premultiplyAlpha &&
!shaderParams.unmultiplyAlpha)
{
shaderParams.srcIsSRGB = false;
shaderParams.destIsSRGB = false;
}
ASSERT(!(params.srcFlipY && params.destFlipY));
if (params.srcFlipY)
{
......
......@@ -321,6 +321,8 @@ class UtilsVk : angle::NonCopyable
uint32_t unmultiplyAlpha = 0;
uint32_t destHasLuminance = 0;
uint32_t destIsAlpha = 0;
uint32_t srcIsSRGB = 0;
uint32_t destIsSRGB = 0;
uint32_t destDefaultChannelsMask = 0;
};
......
......@@ -57,12 +57,53 @@ layout(push_constant) uniform PushConstants {
// Whether destination is emulated luminance/alpha.
bool destHasLuminance;
bool destIsAlpha;
// Whether source or destination are sRGB. They are brought to linear space for alpha
// premultiply/unmultiply, as well as to ensure the copy doesn't change values due to sRGB
// transformation.
bool srcIsSRGB;
bool destIsSRGB;
// Bits 0~3 tell whether R,G,B or A exist in destination, but as a result of format emulation.
// Bit 0 is ignored, because R is always present. For B and G, the result is set to 0 and for
// A, the result is set to 1.
int destDefaultChannelsMask;
} params;
#if SrcIsFloat
float linearToSRGB(float linear)
{
// sRGB transform: y = sRGB(x) where x is linear and y is the sRGB encoding:
//
// x <= 0.0031308: y = x * 12.92
// o.w. : y = 1.055 * x^(1/2.4) - 0.055
if (linear <= 0.0031308)
{
return linear * 12.92;
}
else
{
return pow(linear, (1.0f / 2.4f)) * 1.055f - 0.055f;
}
}
#endif
#if DestIsFloat
float sRGBToLinear(float sRGB)
{
// sRGB inverse transform: x = sRGB^(-1)(y) where x is linear and y is the sRGB encoding:
//
// y <= 0.04045: x = y / 12.92
// o.w. : x = ((y + 0.055) / 1.055)^(2.4)
if (sRGB <= 0.04045)
{
return sRGB / 12.92;
}
else
{
return pow((sRGB + 0.055f) / 1.055f, 2.4f);
}
}
#endif
void main()
{
ivec2 destSubImageCoords = ivec2(gl_FragCoord.xy) - params.destOffset;
......@@ -72,7 +113,9 @@ void main()
// If flipping Y, srcOffset would contain the opposite y coordinate, so we can
// simply reverse the direction in which y grows.
if (params.flipY)
{
srcSubImageCoords.y = -srcSubImageCoords.y;
}
#if SrcIsArray
SrcType srcValue = texelFetch(src, ivec3(params.srcOffset + srcSubImageCoords, params.srcLayer), params.srcMip);
......@@ -80,6 +123,21 @@ void main()
SrcType srcValue = texelFetch(src, params.srcOffset + srcSubImageCoords, params.srcMip);
#endif
// Note: sRGB formats are unorm, so SrcIsFloat must be necessarily set
#if SrcIsFloat
if (params.srcIsSRGB)
{
// If src is sRGB, then texelFetch has performed an sRGB->linear transformation. We need to
// undo that to get back to the original values in the texture. This is done to avoid
// creating a non-sRGB view of the texture, which would require recreating it with the
// VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT flag.
srcValue.r = linearToSRGB(srcValue.r);
srcValue.g = linearToSRGB(srcValue.g);
srcValue.b = linearToSRGB(srcValue.b);
}
#endif
if (params.premultiplyAlpha)
{
srcValue.rgb *= srcValue.a;
......@@ -96,6 +154,25 @@ void main()
// Convert value to destination type.
DestType destValue = DestType(srcValue);
#if !SrcIsFloat && DestIsFloat
destValue /= 255.0;
#endif
// Note: sRGB formats are unorm, so DestIsFloat must be necessarily set
#if DestIsFloat
if (params.destIsSRGB)
{
// If dest is sRGB, then export will perform a linear->sRGB transformation. We need to
// preemptively undo that so the values will be exported unchanged.This is done to avoid
// creating a non-sRGB view of the texture, which would require recreating it with the
// VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT flag.
destValue.r = sRGBToLinear(destValue.r);
destValue.g = sRGBToLinear(destValue.g);
destValue.b = sRGBToLinear(destValue.b);
}
#endif
// If dest is luminance/alpha, it's implemented with R or RG. Do the appropriate swizzle.
if (params.destHasLuminance)
{
......
......@@ -4,15 +4,19 @@
"Use of this source code is governed by a BSD-style license that can be",
"found in the LICENSE file.",
"",
"ImageCopy.frag.json: Build parameters for ImageCopy.frag."
"ImageCopy.frag.json: Build parameters for ImageCopy.frag.",
"",
"Notes:",
" - Optimized ImageCopy shaders crash old AMD drivers. Optimization is tentatively",
" disabled until ANGLE try bots are upgraded. http://anglebug.com/4720"
],
"Flags": [
"SrcIsArray"
],
"SrcFormat": [
"SrcIsFloat",
"SrcIsSint",
"SrcIsUint"
[ "SrcIsFloat", "-Od" ],
[ "SrcIsSint", "-Od" ],
[ "SrcIsUint", "-Od" ]
],
"DestFormat": [
"DestIsFloat",
......
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