Ensure proper SRGB handling


The explicit use of _SRGB dxgi formats or the filtering flags TEX_FILTER_SRGB_IN, TEX_FILTER_SRGB_OUT, TEX_FILTER_SRGB should be respected for conversions, resizing, and mipmap generation. While it is partially implemented, WIC-based conversions and resizing isn't properly using those flags.
Furthermore, Use of IWICFormatConverter implicitly assumes all integer content is sRGB and all fixed/float content is scRGB so there's an implicit conversion of color space which is not desired. This is particularly concerning because for many DXGI formats, this interface is used to convert content to 128bpp float for SIMD-based CPU processing by DirectXTex and then converted back. These code paths all need validation that they properly preserve or change sRGB as requested by the client.
Note: IWICColorTransform is not as useful here as hoped because it will fail when given any fixed-point or floating-point format.
Closed Apr 17, 2013 at 12:51 AM by walbourn


walbourn wrote Mar 12, 2013 at 7:20 PM

SRGB handling is already in the non-WIC based conversion paths, so it appears the best solution here is to remove the use of WIC for format conversions.

For resizing operations, there doesn't appear to be a problem with SRGB changes.

alexandre_mutel wrote Apr 15, 2013 at 8:38 AM

Looking at the code, I'm not completely sure how SRGB is correctly handled for non-WIC path when using mipmaps. For SRGB formats, GenerateMipMaps is using _ConvertToR32G32B32A32 which is only loading a scanline without converting it to linear space (before performing the calculation of the mipmap).

Or do DirectXTex assume that we need to call Convert() method to some RGB float format before calling GenerateMipMaps?

walbourn wrote Apr 15, 2013 at 7:19 PM

I'm actually working on resolving the SRGB problems with Convert now, and should have a release today or tomorrow.

There are a number of ways to handle this;
  1. If your source data is already in sRGB, you may want consider using the 'forceSRGB' option on load-time and not do anything special in the texture processing with DirectXTex1. If you are wanting to explicit convert data to/from sRGB, you'd use Convert() with either the TEX_FILTER_SRGB(_IN|_OUT) flags or a DXGI _SRGB format. This will apply the appropriate Gamma/Degamma.1. All other operations (resize, mipmapping, etc.) should not do any color-space conversion and should simply take place in whatever color-space the source image is in since they are the same on both input and output of these functions. Do you have a scenario where you feel it should only do these in in a linear space?

walbourn wrote Apr 15, 2013 at 7:20 PM

RE: Item #2 above, this is assuming you have the bug fix for this work item in place of course...

alexandre_mutel wrote Apr 16, 2013 at 2:22 AM

Actually, mipmapping for color textures should be computed in linear space and not in srgb space, for exactly the same reason shader lighting should be done in linear space (with texture fetching values in linear space). This problem is described in "The Importance of being Linear", look for mipmap. Also, there is "Gamma and Mimap" that is worth the visual demonstration of calculating a mipmap in srgb instead of linear space.It is not something that is not well known (even Photoshop is doing it wrong!), but working on a fully gamma correct pipeline/rendering is requiring to handle resize/mipmaps carefully regarding srgv/linear spaces

alexandre_mutel wrote Apr 16, 2013 at 2:23 AM

^ meant "not something that is well known"

walbourn wrote Apr 16, 2013 at 5:37 AM

I'll keep that in mind when doing the custom filtering work. WIC-based resize and generate-mipmaps is basically doing to do whatever it wants.

walbourn wrote Apr 17, 2013 at 12:51 AM

Resolved with changeset 26378: DirectXTex: Resolve SRGB handling problems with conversions
  • ComputeMSE flags for sRGB colorspace and channel ignore options