Fix GradingPrimaryTransform OCIO transform in Metal

This transform generates code `if ( gamma != vec3(1., 1., 1.) )`
which is not compatible with Metal.

This patch adds an extra OCIO code processing which converts syntax
to a portable version. It only handles this specific case for the
processing performance reasons.

To reproduce the issue add the following look at the end of the
config.ocio:

```
  - !<Look>
    name: Grading
    process_space: Filmic Log
    description: TEST
    transform: !<GroupTransform>
      children:
        - !<GradingPrimaryTransform>
          style: log
          contrast: {rgb: [0.7, 0.7, 0.7], master: 1}
          saturation: 1.15
          pivot: {contrast: -0.2}
```

Ref #110685

Pull Request: https://projects.blender.org/blender/blender/pulls/111231
This commit is contained in:
Sergey Sharybin 2023-08-17 15:27:51 +02:00 committed by Sergey Sharybin
parent 101c9383d7
commit 259bfc4553
1 changed files with 20 additions and 0 deletions

View File

@ -146,6 +146,15 @@ std::list<OCIO_GPUDisplayShader> SHADER_CACHE;
/** \name Shader
* \{ */
void string_replace_all(std::string &haystack, const std::string &needle, const std::string &other)
{
size_t i = 0, index;
while ((index = haystack.find(needle, i)) != std::string::npos) {
haystack.replace(index, needle.size(), other);
i = index + other.size();
}
}
static bool createGPUShader(OCIO_GPUShader &shader,
OCIO_GPUTextures &textures,
const GpuShaderDescRcPtr &shaderdesc_to_scene_linear,
@ -174,6 +183,17 @@ static bool createGPUShader(OCIO_GPUShader &shader,
}
}
/* Comparison operator in Metal returns per-element comparison and returns a vector of booleans.
* Need a special syntax to see if two vec3 are matched.
*
* NOTE: The replacement is optimized for transforming code generated by
* GradingPrimaryTransform. A more general approach is possible, but for now prefer processing
* speed.
*
* NOTE: The syntax works for all backends Blender supports. */
string_replace_all(
source, "if ( gamma != vec3(1., 1., 1.) )", "if (! all(equal(gamma, vec3(1., 1., 1.))) )");
StageInterfaceInfo iface("OCIO_Interface", "");
iface.smooth(Type::VEC2, "texCoord_interp");