Skip to content

Commit

Permalink
cvpixelbuffer promise sRGB support improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
YuAo committed Feb 11, 2019
1 parent 1eede3d commit ade9086
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 29 deletions.
4 changes: 3 additions & 1 deletion Frameworks/MetalPetal/MTICVPixelBufferPromise.m
Expand Up @@ -305,7 +305,7 @@ - (MTIImagePromiseRenderTarget *)resolveWithContext_MTI:(MTIImageRenderingContex
}

// Render Pipeline
MTLPixelFormat pixelFormat = self.sRGB ? MTLPixelFormatBGRA8Unorm_sRGB : MTLPixelFormatBGRA8Unorm;
MTLPixelFormat pixelFormat = MTLPixelFormatBGRA8Unorm;
MTITextureDescriptor *textureDescriptor = [MTITextureDescriptor texture2DDescriptorWithPixelFormat:pixelFormat width:CVPixelBufferGetWidth(_pixelBuffer) height:CVPixelBufferGetHeight(_pixelBuffer) usage:MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget];
MTIImagePromiseRenderTarget *renderTarget = [renderingContext.context newRenderTargetWithResuableTextureDescriptor:textureDescriptor error:&error];
if (error) {
Expand Down Expand Up @@ -334,6 +334,8 @@ - (MTIImagePromiseRenderTarget *)resolveWithContext_MTI:(MTIImageRenderingContex
[renderCommandEncoder setFragmentTexture:cvMetalTextureY.texture atIndex:0];
[renderCommandEncoder setFragmentTexture:cvMetalTextureCbCr.texture atIndex:1];
[renderCommandEncoder setFragmentBytes:preferredConversion length:sizeof(MTIYUVColorConversion) atIndex:0];
bool convertToLinearRGB = self.sRGB;
[renderCommandEncoder setFragmentBytes:&convertToLinearRGB length:sizeof(convertToLinearRGB) atIndex:1];
[renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4 instanceCount:1];
[renderCommandEncoder endEncoding];

Expand Down
9 changes: 5 additions & 4 deletions Frameworks/MetalPetal/Shaders/ColorConversionShaders.metal
Expand Up @@ -8,6 +8,7 @@

#include <metal_stdlib>
#include <simd/simd.h>
#include "MTIShaderLib.h"

using namespace metal;

Expand Down Expand Up @@ -37,15 +38,15 @@ namespace metalpetal {
return out;
}

fragment half4 colorConversionFragment(Varyings in [[ stage_in ]],
fragment float4 colorConversionFragment(Varyings in [[ stage_in ]],
texture2d<float, access::sample> yTexture [[ texture(0) ]],
texture2d<float, access::sample> cbcrTexture [[ texture(1) ]],
constant ColorConversion &colorConversion [[ buffer(0) ]]) {

constant ColorConversion &colorConversion [[ buffer(0) ]],
constant bool &convertToLinearRGB [[ buffer(1) ]]) {
constexpr sampler s(address::clamp_to_edge, filter::linear);
float3 ycbcr = float3(yTexture.sample(s, in.texcoord).r, cbcrTexture.sample(s, in.texcoord).rg);
float3 rgb = colorConversion.matrix * (ycbcr + colorConversion.offset);
return half4(half3(rgb), 1.0);
return float4(float3(convertToLinearRGB ? sRGBToLinear(rgb) : rgb), 1.0);
}

kernel void colorConversion(uint2 gid [[ thread_position_in_grid ]],
Expand Down
43 changes: 19 additions & 24 deletions Frameworks/MetalPetal/Shaders/MTIShaderLib.h
Expand Up @@ -60,14 +60,27 @@ namespace metalpetal {
} VertexOut;

// GLSL mod func for metal
template <typename T, typename _E = typename enable_if<is_same<float, typename make_scalar<T>::type>::value>::type>
template <typename T, typename _E = typename enable_if<is_floating_point<typename make_scalar<T>::type>::value>::type>
METAL_FUNC T mod(T x, T y) {
return x - y * floor(x/y);
}

template <typename T, typename _E = typename enable_if<is_same<float, typename make_scalar<T>::type>::value>::type>
METAL_FUNC T sRGBToLinear(T x) {
return sign(x)*mix(abs(x)*0.077399380804954, pow(abs(x)*0.947867298578199 + 0.052132701421801, 2.4), step(0.04045, abs(x)));
template <typename T, typename _E = typename enable_if<is_floating_point<T>::value>::type>
METAL_FUNC T sRGBToLinear(T c) {
return (c <= 0.04045f) ? c / 12.92f : powr((c + 0.055f) / 1.055f, 2.4f);
}

METAL_FUNC float3 sRGBToLinear(float3 c) {
return float3(sRGBToLinear(c.r), sRGBToLinear(c.g), sRGBToLinear(c.b));
}

template <typename T, typename _E = typename enable_if<is_floating_point<T>::value>::type>
METAL_FUNC T linearToSRGB(T c) {
return (c < 0.0031308f) ? (12.92f * c) : (1.055f * powr(c, 1.f/2.4f) - 0.055f);
}

METAL_FUNC float3 linearToSRGB(float3 c) {
return float3(linearToSRGB(c.r), linearToSRGB(c.g), linearToSRGB(c.b));
}

METAL_FUNC float4 unpremultiply(float4 s) {
Expand All @@ -78,26 +91,8 @@ namespace metalpetal {
return float4(s.rgb * s.a, s.a);
}

METAL_FUNC float hue2rgb(float p, float q, float t){
if(t < 0.0) {
t += 1.0;
}
if(t > 1.0) {
t -= 1.0;
}
if(t < 1.0/6.0) {
return p + (q - p) * 6.0 * t;
}
if(t < 1.0/2.0) {
return q;
}
if(t < 2.0/3.0) {
return p + (q - p) * (2.0/3.0 - t) * 6.0;
}
return p;
}

METAL_FUNC half hue2rgb(half p, half q, half t){
template <typename T, typename _E = typename enable_if<is_floating_point<T>::value>::type>
METAL_FUNC T hue2rgb(T p, T q, T t){
if(t < 0.0) {
t += 1.0;
}
Expand Down

0 comments on commit ade9086

Please sign in to comment.