Skip to content

Possible bug in optimizer with colorspace transform with mixed scene referred/display colorspaces #2180

@SRHMorris

Description

@SRHMorris

I'm unsure if this is really a bug or not, as I'm unsure if using display colorspaces with scene referred colorspaces in a OCIO::ColorSpaceTransform is valid (i.e. not a DisplayViewTransform).

Here's my code, with OCIO v2.4.2.

auto config = OCIO::Config::CreateFromFile("ocio://default");

auto cst = OCIO::ColorSpaceTransform::Create();
cst->setDst("Rec.1886 Rec.709 - Display");
// cst->setSrc("Linear Rec.709 (sRGB)");
cst->setSrc("Gamma 2.4 Encoded Rec.709"); // <- this causes issue

auto group = OCIO::GroupTransform::Create();
group->appendTransform(cst);

auto proc = config->getProcessor(group)->getOptimizedGPUProcessor(OCIO::OptimizationFlags::OPTIMIZATION_LOSSLESS); // <- setting to NONE fixes it

auto gpuShaderInfo = OCIO::GpuShaderDesc::CreateShaderDesc();
gpuShaderInfo->setLanguage(OCIO::GpuLanguage::GPU_LANGUAGE_HLSL_SM_5_0);
proc->extractGpuShaderInfo(gpuShaderInfo);

const char *text = gpuShaderInfo->getShaderText();
std::cout << text << std::endl;

With the linear Rec709 space set as the source, I get the following shader text which is what I'd expect, e.g. just a 2.4 gamma transform:

// Declaration of the OCIO shader function

float4 OCIOMain(float4 inPixel)
{
  float4 outColor = inPixel;
  
  // Add Gamma 'basicRev' processing
  
  {
    float4 gamma = float4(0.41666666666666669, 0.41666666666666669, 0.41666666666666669, 1.);
    float4 res = pow( max( float4(0., 0., 0., 0.), outColor ), gamma );
    outColor.rgb = float3(res.x, res.y, res.z);
    outColor.a = res.w;
  }

  return outColor;
}

However with the 2.4 gamma space set as the source, I'd expect a no-op transform. Instead I get this (a gamma of 5.76?):

// Declaration of the OCIO shader function

float4 OCIOMain(float4 inPixel)
{
  float4 outColor = inPixel;
  
  // Add Gamma 'basicRev' processing
  
  {
    float4 gamma = float4(0.17361111111111113, 0.17361111111111113, 0.17361111111111113, 1.);
    float4 res = pow( max( float4(0., 0., 0., 0.), outColor ), gamma );
    outColor.rgb = float3(res.x, res.y, res.z);
    outColor.a = res.w;
  }

  return outColor;
}

With OPTIMIZATION_NONE it seems reasonable:

// Declaration of the OCIO shader function

float4 OCIOMain(float4 inPixel)
{
  float4 outColor = inPixel;
  
  // Add Gamma 'basicPassThruFwd' processing
  
  {
    float4 gamma = float4(2.3999999999999999, 2.3999999999999999, 2.3999999999999999, 1.);
    float4 breakPnt = float4(0., 0., 0., 0.);
    float4 isAboveBreak = float4((outColor[0] > breakPnt[0]) ? 1.0 : 0.0, (outColor[1] > breakPnt[1]) ? 1.0 : 0.0, (outColor[2] > breakPnt[2]) ? 1.0 : 0.0, (outColor[3] > breakPnt[3]) ? 1.0 : 0.0);
    float4 powSeg = pow(max( float4(0., 0., 0., 0.), outColor ), gamma);
    float4 res = isAboveBreak * powSeg + ( float4(1., 1., 1., 1.) - isAboveBreak ) * outColor;
    outColor.rgb = float3(res.x, res.y, res.z);
    outColor.a = res.w;
  }
  
  // Add Matrix processing
  
  {
    float4 res = float4(outColor.rgb.r, outColor.rgb.g, outColor.rgb.b, outColor.a);
    float4 tmp = res;
    res = mul(tmp, float4x4(0.43963298191949191, 0.089776442958842226, 0.017541170383172787, 0., 0.38298869815155351, 0.81343942874897801, 0.11154655330238722, 0., 0.1773783199289555, 0.096784128292177099, 0.87091227631444246, 0., 0., 0., 0., 1.));
    outColor.rgb = float3(res.x, res.y, res.z);
    outColor.a = res.w;
  }
  
  // Add Matrix processing
  
  {
    float4 res = float4(outColor.rgb.r, outColor.rgb.g, outColor.rgb.b, outColor.a);
    float4 tmp = res;
    res = mul(tmp, float4x4(0.93827984927725538, 0.33736889078783672, 0.0011739508496858789, 0., -0.0044514458123613987, 0.72952156669026536, -0.0037107064020525625, 0., 0.016627523586776168, -0.066890457478102336, 1.0915945063122465, 0., 0., 0., 0., 1.));
    outColor.rgb = float3(res.x, res.y, res.z);
    outColor.a = res.w;
  }
  
  // Add Matrix processing
  
  {
    float4 res = float4(outColor.rgb.r, outColor.rgb.g, outColor.rgb.b, outColor.a);
    float4 tmp = res;
    res = mul(tmp, float4x4(3.2409699419045213, -0.96924363628087973, 0.055630079696993649, 0., -1.5373831775700932, 1.8759675015077204, -0.20397695888897652, 0., -0.4986107602930035, 0.04155505740717564, 1.0569715142428788, 0., 0., 0., 0., 1.));
    outColor.rgb = float3(res.x, res.y, res.z);
    outColor.a = res.w;
  }
  
  // Add Gamma 'basicRev' processing
  
  {
    float4 gamma = float4(0.41666666666666669, 0.41666666666666669, 0.41666666666666669, 1.);
    float4 res = pow( max( float4(0., 0., 0., 0.), outColor ), gamma );
    outColor.rgb = float3(res.x, res.y, res.z);
    outColor.a = res.w;
  }

  return outColor;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions