| Message ID | 20250824-b4-v0-5-2-gpuisp-v2-a-v2-28-96f4576c814e@linaro.org |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
Hi 2025. 08. 24. 2:48 keltezéssel, Bryan O'Donoghue írta: > Extend out the bayer fragment shaders to take 3 x 256 byte inputs as > textures from the CPU. > > We then use an index to the table to recover the colour-corrected values > provided by the SoftIPA thread. > > Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> > --- > .../internal/shaders/bayer_1x_packed.frag | 56 +++++++++++++++++++ > include/libcamera/internal/shaders/bayer_8.frag | 62 +++++++++++++++++++++- > 2 files changed, 117 insertions(+), 1 deletion(-) > > diff --git a/include/libcamera/internal/shaders/bayer_1x_packed.frag b/include/libcamera/internal/shaders/bayer_1x_packed.frag > index 19b13ad08b3a71e408774dbb8e75ca4e22d9ba8e..90bd645709e02d8cf9bee112b25cbb26c681db0a 100644 > --- a/include/libcamera/internal/shaders/bayer_1x_packed.frag > +++ b/include/libcamera/internal/shaders/bayer_1x_packed.frag > @@ -65,6 +65,10 @@ uniform vec2 tex_step; > uniform vec2 tex_bayer_first_red; > > uniform sampler2D tex_y; > +uniform sampler2D red_param; > +uniform sampler2D green_param; > +uniform sampler2D blue_param; > +uniform mat3 ccm; > > void main(void) > { > @@ -212,5 +216,57 @@ void main(void) > vec3(patterns.y, C, patterns.x) : > vec3(patterns.wz, C)); > > +#if defined(APPLY_CCM_PARAMETERS) > + /* > + * CCM is a 3x3 in the format > + * > + * +--------------+----------------+---------------+ > + * | RedRedGain | RedGreenGain | RedBlueGain | > + * +--------------+----------------+---------------+ > + * | GreenRedGain | GreenGreenGain | GreenBlueGain | > + * +--------------+----------------+---------------+ > + * | BlueRedGain | BlueGreenGain | BlueBlueGain | > + * +--------------+----------------+---------------+ > + * > + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin > + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin > + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin > + * > + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); > + * > + * CPU > + * float ccm [] = { > + * RedRedGain, RedGreenGain, RedBlueGain, > + * GreenRedGain, GreenGreenGain, GreenBlueGain, > + * BlueRedGain, BlueGreenGain, BlueBlueGain, > + * }; > + * > + * GPU > + * ccm = { > + * RedRedGain, GreenRedGain, BlueRedGain, > + * RedGreenGain, GreenGreenGain, BlueGreenGain, > + * RedBlueGain, GreenBlueGain, BlueBlueGain, > + * } > + * > + * However the indexing for the mat data-type is column major hence > + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain > + * > + */ > + float rin, gin, bin; > + rin = rgb.r; > + gin = rgb.g; > + bin = rgb.b; > + > + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); > + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); > + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); > + > +#elif defined(APPLY_RGB_PARAMETERS) > + /* Apply bayer params */ > + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; > + rgb.g = texture2D(green_param, vec2(rgb.g, 0.5)).g; > + rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; > +#endif > + > gl_FragColor = vec4(rgb, 1.0); > } > diff --git a/include/libcamera/internal/shaders/bayer_8.frag b/include/libcamera/internal/shaders/bayer_8.frag > index aa7a1b00436ae15d2ed6af7d666441d20db6bb0b..5955c2eafbe03678158b240740e18c7f00e58057 100644 > --- a/include/libcamera/internal/shaders/bayer_8.frag > +++ b/include/libcamera/internal/shaders/bayer_8.frag > @@ -21,11 +21,17 @@ precision highp float; > > /** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/ > uniform sampler2D tex_y; > +uniform sampler2D red_param; > +uniform sampler2D green_param; > +uniform sampler2D blue_param; > varying vec4 center; > varying vec4 yCoord; > varying vec4 xCoord; > +uniform mat3 ccm; > > void main(void) { > + vec3 rgb; > + > #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r > > float C = texture2D(tex_y, center.xy).r; // ( 0, 0) > @@ -97,11 +103,65 @@ void main(void) { > PATTERN.xw += kB.xw * B; > PATTERN.xz += kF.xz * F; > > - gl_FragColor.rgb = (alternate.y == 0.0) ? > + rgb = (alternate.y == 0.0) ? > ((alternate.x == 0.0) ? > vec3(C, PATTERN.xy) : > vec3(PATTERN.z, C, PATTERN.w)) : > ((alternate.x == 0.0) ? > vec3(PATTERN.w, C, PATTERN.z) : > vec3(PATTERN.yx, C)); > + > +#if defined(APPLY_CCM_PARAMETERS) > + /* > + * CCM is a 3x3 in the format > + * > + * +--------------+----------------+---------------+ > + * | RedRedGain | RedGreenGain | RedBlueGain | > + * +--------------+----------------+---------------+ > + * | GreenRedGain | GreenGreenGain | GreenBlueGain | > + * +--------------+----------------+---------------+ > + * | BlueRedGain | BlueGreenGain | BlueBlueGain | > + * +--------------+----------------+---------------+ > + * > + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin > + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin > + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin > + * > + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); > + * > + * CPU > + * float ccm [] = { > + * RedRedGain, RedGreenGain, RedBlueGain, > + * GreenRedGain, GreenGreenGain, GreenBlueGain, > + * BlueRedGain, BlueGreenGain, BlueBlueGain, > + * }; > + * > + * GPU > + * ccm = { > + * RedRedGain, GreenRedGain, BlueRedGain, > + * RedGreenGain, GreenGreenGain, BlueGreenGain, > + * RedBlueGain, GreenBlueGain, BlueBlueGain, > + * } > + * > + * However the indexing for the mat data-type is column major hence > + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain > + * > + */ > + float rin, gin, bin; > + rin = rgb.r; > + gin = rgb.g; > + bin = rgb.b; > + > + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); > + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); > + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); Is there any downside to making `rgb = rgb * ccm` or similar work instead of manual multiplication? > + > +#elif defined(APPLY_RGB_PARAMETERS) > + /* Apply bayer params */ > + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; > + rgb.g = texture2D(red_param, vec2(rgb.g, 0.5)).g; green_param ? > + rgb.b = texture2D(red_param, vec2(rgb.b, 0.5)).b; blue_param ? Regards, Barnabás Pőcze > +#endif > + > + gl_FragColor.rgb = rgb; > } >
On 25/09/2025 16:10, Barnabás Pőcze wrote: > Hi > > > 2025. 08. 24. 2:48 keltezéssel, Bryan O'Donoghue írta: >> Extend out the bayer fragment shaders to take 3 x 256 byte inputs as >> textures from the CPU. >> >> We then use an index to the table to recover the colour-corrected values >> provided by the SoftIPA thread. >> >> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> >> --- >> .../internal/shaders/bayer_1x_packed.frag | 56 +++++++++++++++++++ >> include/libcamera/internal/shaders/bayer_8.frag | 62 +++++++++++++++++++++- >> 2 files changed, 117 insertions(+), 1 deletion(-) >> >> diff --git a/include/libcamera/internal/shaders/bayer_1x_packed.frag b/include/libcamera/internal/shaders/bayer_1x_packed.frag >> index 19b13ad08b3a71e408774dbb8e75ca4e22d9ba8e..90bd645709e02d8cf9bee112b25cbb26c681db0a 100644 >> --- a/include/libcamera/internal/shaders/bayer_1x_packed.frag >> +++ b/include/libcamera/internal/shaders/bayer_1x_packed.frag >> @@ -65,6 +65,10 @@ uniform vec2 tex_step; >> uniform vec2 tex_bayer_first_red; >> >> uniform sampler2D tex_y; >> +uniform sampler2D red_param; >> +uniform sampler2D green_param; >> +uniform sampler2D blue_param; >> +uniform mat3 ccm; >> >> void main(void) >> { >> @@ -212,5 +216,57 @@ void main(void) >> vec3(patterns.y, C, patterns.x) : >> vec3(patterns.wz, C)); >> >> +#if defined(APPLY_CCM_PARAMETERS) >> + /* >> + * CCM is a 3x3 in the format >> + * >> + * +--------------+----------------+---------------+ >> + * | RedRedGain | RedGreenGain | RedBlueGain | >> + * +--------------+----------------+---------------+ >> + * | GreenRedGain | GreenGreenGain | GreenBlueGain | >> + * +--------------+----------------+---------------+ >> + * | BlueRedGain | BlueGreenGain | BlueBlueGain | >> + * +--------------+----------------+---------------+ >> + * >> + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin >> + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin >> + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin >> + * >> + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); >> + * >> + * CPU >> + * float ccm [] = { >> + * RedRedGain, RedGreenGain, RedBlueGain, >> + * GreenRedGain, GreenGreenGain, GreenBlueGain, >> + * BlueRedGain, BlueGreenGain, BlueBlueGain, >> + * }; >> + * >> + * GPU >> + * ccm = { >> + * RedRedGain, GreenRedGain, BlueRedGain, >> + * RedGreenGain, GreenGreenGain, BlueGreenGain, >> + * RedBlueGain, GreenBlueGain, BlueBlueGain, >> + * } >> + * >> + * However the indexing for the mat data-type is column major hence >> + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain >> + * >> + */ >> + float rin, gin, bin; >> + rin = rgb.r; >> + gin = rgb.g; >> + bin = rgb.b; >> + >> + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); >> + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); >> + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); >> + >> +#elif defined(APPLY_RGB_PARAMETERS) >> + /* Apply bayer params */ >> + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; >> + rgb.g = texture2D(green_param, vec2(rgb.g, 0.5)).g; >> + rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; >> +#endif >> + >> gl_FragColor = vec4(rgb, 1.0); >> } >> diff --git a/include/libcamera/internal/shaders/bayer_8.frag b/include/libcamera/internal/shaders/bayer_8.frag >> index aa7a1b00436ae15d2ed6af7d666441d20db6bb0b..5955c2eafbe03678158b240740e18c7f00e58057 100644 >> --- a/include/libcamera/internal/shaders/bayer_8.frag >> +++ b/include/libcamera/internal/shaders/bayer_8.frag >> @@ -21,11 +21,17 @@ precision highp float; >> >> /** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/ >> uniform sampler2D tex_y; >> +uniform sampler2D red_param; >> +uniform sampler2D green_param; >> +uniform sampler2D blue_param; >> varying vec4 center; >> varying vec4 yCoord; >> varying vec4 xCoord; >> +uniform mat3 ccm; >> >> void main(void) { >> + vec3 rgb; >> + >> #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r >> >> float C = texture2D(tex_y, center.xy).r; // ( 0, 0) >> @@ -97,11 +103,65 @@ void main(void) { >> PATTERN.xw += kB.xw * B; >> PATTERN.xz += kF.xz * F; >> >> - gl_FragColor.rgb = (alternate.y == 0.0) ? >> + rgb = (alternate.y == 0.0) ? >> ((alternate.x == 0.0) ? >> vec3(C, PATTERN.xy) : >> vec3(PATTERN.z, C, PATTERN.w)) : >> ((alternate.x == 0.0) ? >> vec3(PATTERN.w, C, PATTERN.z) : >> vec3(PATTERN.yx, C)); >> + >> +#if defined(APPLY_CCM_PARAMETERS) >> + /* >> + * CCM is a 3x3 in the format >> + * >> + * +--------------+----------------+---------------+ >> + * | RedRedGain | RedGreenGain | RedBlueGain | >> + * +--------------+----------------+---------------+ >> + * | GreenRedGain | GreenGreenGain | GreenBlueGain | >> + * +--------------+----------------+---------------+ >> + * | BlueRedGain | BlueGreenGain | BlueBlueGain | >> + * +--------------+----------------+---------------+ >> + * >> + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin >> + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin >> + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin >> + * >> + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); >> + * >> + * CPU >> + * float ccm [] = { >> + * RedRedGain, RedGreenGain, RedBlueGain, >> + * GreenRedGain, GreenGreenGain, GreenBlueGain, >> + * BlueRedGain, BlueGreenGain, BlueBlueGain, >> + * }; >> + * >> + * GPU >> + * ccm = { >> + * RedRedGain, GreenRedGain, BlueRedGain, >> + * RedGreenGain, GreenGreenGain, BlueGreenGain, >> + * RedBlueGain, GreenBlueGain, BlueBlueGain, >> + * } >> + * >> + * However the indexing for the mat data-type is column major hence >> + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain >> + * >> + */ >> + float rin, gin, bin; >> + rin = rgb.r; >> + gin = rgb.g; >> + bin = rgb.b; >> + >> + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); >> + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); >> + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); > > Is there any downside to making `rgb = rgb * ccm` or similar work instead > of manual multiplication? ... No I think that will work just as well. > > >> + >> +#elif defined(APPLY_RGB_PARAMETERS) >> + /* Apply bayer params */ >> + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; >> + rgb.g = texture2D(red_param, vec2(rgb.g, 0.5)).g; > > green_param ? > >> + rgb.b = texture2D(red_param, vec2(rgb.b, 0.5)).b; > > blue_param ? Yep already noticed this thx: https://gitlab.freedesktop.org/camera/libcamera-softisp/-/blob/v0.5.2-gpuisp-v2-a+kbingham-agc/include/libcamera/internal/shaders/bayer_1x_packed.frag?ref_type=heads#L264> > > Regards, > Barnabás Pőcze > --- bod
On 25/09/2025 16:10, Barnabás Pőcze wrote: > Hi > > > 2025. 08. 24. 2:48 keltezéssel, Bryan O'Donoghue írta: >> Extend out the bayer fragment shaders to take 3 x 256 byte inputs as >> textures from the CPU. >> >> We then use an index to the table to recover the colour-corrected values >> provided by the SoftIPA thread. >> >> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> >> --- >> .../internal/shaders/bayer_1x_packed.frag | 56 +++++++++++++++++++ >> include/libcamera/internal/shaders/bayer_8.frag | 62 +++++++++++++++++++++- >> 2 files changed, 117 insertions(+), 1 deletion(-) >> >> diff --git a/include/libcamera/internal/shaders/bayer_1x_packed.frag b/include/libcamera/internal/shaders/bayer_1x_packed.frag >> index 19b13ad08b3a71e408774dbb8e75ca4e22d9ba8e..90bd645709e02d8cf9bee112b25cbb26c681db0a 100644 >> --- a/include/libcamera/internal/shaders/bayer_1x_packed.frag >> +++ b/include/libcamera/internal/shaders/bayer_1x_packed.frag >> @@ -65,6 +65,10 @@ uniform vec2 tex_step; >> uniform vec2 tex_bayer_first_red; >> >> uniform sampler2D tex_y; >> +uniform sampler2D red_param; >> +uniform sampler2D green_param; >> +uniform sampler2D blue_param; >> +uniform mat3 ccm; >> >> void main(void) >> { >> @@ -212,5 +216,57 @@ void main(void) >> vec3(patterns.y, C, patterns.x) : >> vec3(patterns.wz, C)); >> >> +#if defined(APPLY_CCM_PARAMETERS) >> + /* >> + * CCM is a 3x3 in the format >> + * >> + * +--------------+----------------+---------------+ >> + * | RedRedGain | RedGreenGain | RedBlueGain | >> + * +--------------+----------------+---------------+ >> + * | GreenRedGain | GreenGreenGain | GreenBlueGain | >> + * +--------------+----------------+---------------+ >> + * | BlueRedGain | BlueGreenGain | BlueBlueGain | >> + * +--------------+----------------+---------------+ >> + * >> + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin >> + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin >> + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin >> + * >> + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); >> + * >> + * CPU >> + * float ccm [] = { >> + * RedRedGain, RedGreenGain, RedBlueGain, >> + * GreenRedGain, GreenGreenGain, GreenBlueGain, >> + * BlueRedGain, BlueGreenGain, BlueBlueGain, >> + * }; >> + * >> + * GPU >> + * ccm = { >> + * RedRedGain, GreenRedGain, BlueRedGain, >> + * RedGreenGain, GreenGreenGain, BlueGreenGain, >> + * RedBlueGain, GreenBlueGain, BlueBlueGain, >> + * } >> + * >> + * However the indexing for the mat data-type is column major hence >> + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain >> + * >> + */ >> + float rin, gin, bin; >> + rin = rgb.r; >> + gin = rgb.g; >> + bin = rgb.b; >> + >> + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); >> + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); >> + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); >> + >> +#elif defined(APPLY_RGB_PARAMETERS) >> + /* Apply bayer params */ >> + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; >> + rgb.g = texture2D(green_param, vec2(rgb.g, 0.5)).g; >> + rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; >> +#endif >> + >> gl_FragColor = vec4(rgb, 1.0); >> } >> diff --git a/include/libcamera/internal/shaders/bayer_8.frag b/include/libcamera/internal/shaders/bayer_8.frag >> index aa7a1b00436ae15d2ed6af7d666441d20db6bb0b..5955c2eafbe03678158b240740e18c7f00e58057 100644 >> --- a/include/libcamera/internal/shaders/bayer_8.frag >> +++ b/include/libcamera/internal/shaders/bayer_8.frag >> @@ -21,11 +21,17 @@ precision highp float; >> >> /** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/ >> uniform sampler2D tex_y; >> +uniform sampler2D red_param; >> +uniform sampler2D green_param; >> +uniform sampler2D blue_param; >> varying vec4 center; >> varying vec4 yCoord; >> varying vec4 xCoord; >> +uniform mat3 ccm; >> >> void main(void) { >> + vec3 rgb; >> + >> #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r >> >> float C = texture2D(tex_y, center.xy).r; // ( 0, 0) >> @@ -97,11 +103,65 @@ void main(void) { >> PATTERN.xw += kB.xw * B; >> PATTERN.xz += kF.xz * F; >> >> - gl_FragColor.rgb = (alternate.y == 0.0) ? >> + rgb = (alternate.y == 0.0) ? >> ((alternate.x == 0.0) ? >> vec3(C, PATTERN.xy) : >> vec3(PATTERN.z, C, PATTERN.w)) : >> ((alternate.x == 0.0) ? >> vec3(PATTERN.w, C, PATTERN.z) : >> vec3(PATTERN.yx, C)); >> + >> +#if defined(APPLY_CCM_PARAMETERS) >> + /* >> + * CCM is a 3x3 in the format >> + * >> + * +--------------+----------------+---------------+ >> + * | RedRedGain | RedGreenGain | RedBlueGain | >> + * +--------------+----------------+---------------+ >> + * | GreenRedGain | GreenGreenGain | GreenBlueGain | >> + * +--------------+----------------+---------------+ >> + * | BlueRedGain | BlueGreenGain | BlueBlueGain | >> + * +--------------+----------------+---------------+ >> + * >> + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin >> + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin >> + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin >> + * >> + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); >> + * >> + * CPU >> + * float ccm [] = { >> + * RedRedGain, RedGreenGain, RedBlueGain, >> + * GreenRedGain, GreenGreenGain, GreenBlueGain, >> + * BlueRedGain, BlueGreenGain, BlueBlueGain, >> + * }; >> + * >> + * GPU >> + * ccm = { >> + * RedRedGain, GreenRedGain, BlueRedGain, >> + * RedGreenGain, GreenGreenGain, BlueGreenGain, >> + * RedBlueGain, GreenBlueGain, BlueBlueGain, >> + * } >> + * >> + * However the indexing for the mat data-type is column major hence >> + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain >> + * >> + */ >> + float rin, gin, bin; >> + rin = rgb.r; >> + gin = rgb.g; >> + bin = rgb.b; >> + >> + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); >> + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); >> + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); > > Is there any downside to making `rgb = rgb * ccm` or similar work instead > of manual multiplication? I didn't do this because the code is I think easier to understand this way without loosing any performance. >> + >> +#elif defined(APPLY_RGB_PARAMETERS) >> + /* Apply bayer params */ >> + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; >> + rgb.g = texture2D(red_param, vec2(rgb.g, 0.5)).g; > > green_param ? > >> + rgb.b = texture2D(red_param, vec2(rgb.b, 0.5)).b; > > blue_param ? I very much did this though :) --- bod
2025. 10. 06. 23:13 keltezéssel, Bryan O'Donoghue írta: > On 25/09/2025 16:10, Barnabás Pőcze wrote: >> Hi >> >> >> 2025. 08. 24. 2:48 keltezéssel, Bryan O'Donoghue írta: >>> Extend out the bayer fragment shaders to take 3 x 256 byte inputs as >>> textures from the CPU. >>> >>> We then use an index to the table to recover the colour-corrected values >>> provided by the SoftIPA thread. >>> >>> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> >>> --- >>> .../internal/shaders/bayer_1x_packed.frag | 56 +++++++++++++++++++ >>> include/libcamera/internal/shaders/bayer_8.frag | 62 +++++++++++++++++++++- >>> 2 files changed, 117 insertions(+), 1 deletion(-) >>> > [...] >>> diff --git a/include/libcamera/internal/shaders/bayer_8.frag b/include/libcamera/internal/shaders/bayer_8.frag >>> index aa7a1b00436ae15d2ed6af7d666441d20db6bb0b..5955c2eafbe03678158b240740e18c7f00e58057 100644 >>> --- a/include/libcamera/internal/shaders/bayer_8.frag >>> +++ b/include/libcamera/internal/shaders/bayer_8.frag >>> @@ -21,11 +21,17 @@ precision highp float; >>> >>> /** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/ >>> uniform sampler2D tex_y; >>> +uniform sampler2D red_param; >>> +uniform sampler2D green_param; >>> +uniform sampler2D blue_param; >>> varying vec4 center; >>> varying vec4 yCoord; >>> varying vec4 xCoord; >>> +uniform mat3 ccm; >>> >>> void main(void) { >>> + vec3 rgb; >>> + >>> #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r >>> >>> float C = texture2D(tex_y, center.xy).r; // ( 0, 0) >>> @@ -97,11 +103,65 @@ void main(void) { >>> PATTERN.xw += kB.xw * B; >>> PATTERN.xz += kF.xz * F; >>> >>> - gl_FragColor.rgb = (alternate.y == 0.0) ? >>> + rgb = (alternate.y == 0.0) ? >>> ((alternate.x == 0.0) ? >>> vec3(C, PATTERN.xy) : >>> vec3(PATTERN.z, C, PATTERN.w)) : >>> ((alternate.x == 0.0) ? >>> vec3(PATTERN.w, C, PATTERN.z) : >>> vec3(PATTERN.yx, C)); >>> + >>> +#if defined(APPLY_CCM_PARAMETERS) >>> + /* >>> + * CCM is a 3x3 in the format >>> + * >>> + * +--------------+----------------+---------------+ >>> + * | RedRedGain | RedGreenGain | RedBlueGain | >>> + * +--------------+----------------+---------------+ >>> + * | GreenRedGain | GreenGreenGain | GreenBlueGain | >>> + * +--------------+----------------+---------------+ >>> + * | BlueRedGain | BlueGreenGain | BlueBlueGain | >>> + * +--------------+----------------+---------------+ >>> + * >>> + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin >>> + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin >>> + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin >>> + * >>> + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); >>> + * >>> + * CPU >>> + * float ccm [] = { >>> + * RedRedGain, RedGreenGain, RedBlueGain, >>> + * GreenRedGain, GreenGreenGain, GreenBlueGain, >>> + * BlueRedGain, BlueGreenGain, BlueBlueGain, >>> + * }; >>> + * >>> + * GPU >>> + * ccm = { >>> + * RedRedGain, GreenRedGain, BlueRedGain, >>> + * RedGreenGain, GreenGreenGain, BlueGreenGain, >>> + * RedBlueGain, GreenBlueGain, BlueBlueGain, >>> + * } >>> + * >>> + * However the indexing for the mat data-type is column major hence >>> + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain >>> + * >>> + */ >>> + float rin, gin, bin; >>> + rin = rgb.r; >>> + gin = rgb.g; >>> + bin = rgb.b; >>> + >>> + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); >>> + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); >>> + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); >> >> Is there any downside to making `rgb = rgb * ccm` or similar work instead >> of manual multiplication? > > I didn't do this because the code is I think easier to understand this > way without loosing any performance. I see, in my mind there wasn't any doubt that `rgb * ccm` is easier to read, well, at least to me. Regards, Barnabás Pőcze > >>> + >>> +#elif defined(APPLY_RGB_PARAMETERS) >>> + /* Apply bayer params */ >>> + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; >>> + rgb.g = texture2D(red_param, vec2(rgb.g, 0.5)).g; >> >> green_param ? >> >>> + rgb.b = texture2D(red_param, vec2(rgb.b, 0.5)).b; >> >> blue_param ? > > I very much did this though :) > > --- > bod >
diff --git a/include/libcamera/internal/shaders/bayer_1x_packed.frag b/include/libcamera/internal/shaders/bayer_1x_packed.frag index 19b13ad08b3a71e408774dbb8e75ca4e22d9ba8e..90bd645709e02d8cf9bee112b25cbb26c681db0a 100644 --- a/include/libcamera/internal/shaders/bayer_1x_packed.frag +++ b/include/libcamera/internal/shaders/bayer_1x_packed.frag @@ -65,6 +65,10 @@ uniform vec2 tex_step; uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; +uniform sampler2D red_param; +uniform sampler2D green_param; +uniform sampler2D blue_param; +uniform mat3 ccm; void main(void) { @@ -212,5 +216,57 @@ void main(void) vec3(patterns.y, C, patterns.x) : vec3(patterns.wz, C)); +#if defined(APPLY_CCM_PARAMETERS) + /* + * CCM is a 3x3 in the format + * + * +--------------+----------------+---------------+ + * | RedRedGain | RedGreenGain | RedBlueGain | + * +--------------+----------------+---------------+ + * | GreenRedGain | GreenGreenGain | GreenBlueGain | + * +--------------+----------------+---------------+ + * | BlueRedGain | BlueGreenGain | BlueBlueGain | + * +--------------+----------------+---------------+ + * + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin + * + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); + * + * CPU + * float ccm [] = { + * RedRedGain, RedGreenGain, RedBlueGain, + * GreenRedGain, GreenGreenGain, GreenBlueGain, + * BlueRedGain, BlueGreenGain, BlueBlueGain, + * }; + * + * GPU + * ccm = { + * RedRedGain, GreenRedGain, BlueRedGain, + * RedGreenGain, GreenGreenGain, BlueGreenGain, + * RedBlueGain, GreenBlueGain, BlueBlueGain, + * } + * + * However the indexing for the mat data-type is column major hence + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain + * + */ + float rin, gin, bin; + rin = rgb.r; + gin = rgb.g; + bin = rgb.b; + + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + +#elif defined(APPLY_RGB_PARAMETERS) + /* Apply bayer params */ + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; + rgb.g = texture2D(green_param, vec2(rgb.g, 0.5)).g; + rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; +#endif + gl_FragColor = vec4(rgb, 1.0); } diff --git a/include/libcamera/internal/shaders/bayer_8.frag b/include/libcamera/internal/shaders/bayer_8.frag index aa7a1b00436ae15d2ed6af7d666441d20db6bb0b..5955c2eafbe03678158b240740e18c7f00e58057 100644 --- a/include/libcamera/internal/shaders/bayer_8.frag +++ b/include/libcamera/internal/shaders/bayer_8.frag @@ -21,11 +21,17 @@ precision highp float; /** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/ uniform sampler2D tex_y; +uniform sampler2D red_param; +uniform sampler2D green_param; +uniform sampler2D blue_param; varying vec4 center; varying vec4 yCoord; varying vec4 xCoord; +uniform mat3 ccm; void main(void) { + vec3 rgb; + #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r float C = texture2D(tex_y, center.xy).r; // ( 0, 0) @@ -97,11 +103,65 @@ void main(void) { PATTERN.xw += kB.xw * B; PATTERN.xz += kF.xz * F; - gl_FragColor.rgb = (alternate.y == 0.0) ? + rgb = (alternate.y == 0.0) ? ((alternate.x == 0.0) ? vec3(C, PATTERN.xy) : vec3(PATTERN.z, C, PATTERN.w)) : ((alternate.x == 0.0) ? vec3(PATTERN.w, C, PATTERN.z) : vec3(PATTERN.yx, C)); + +#if defined(APPLY_CCM_PARAMETERS) + /* + * CCM is a 3x3 in the format + * + * +--------------+----------------+---------------+ + * | RedRedGain | RedGreenGain | RedBlueGain | + * +--------------+----------------+---------------+ + * | GreenRedGain | GreenGreenGain | GreenBlueGain | + * +--------------+----------------+---------------+ + * | BlueRedGain | BlueGreenGain | BlueBlueGain | + * +--------------+----------------+---------------+ + * + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin + * + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); + * + * CPU + * float ccm [] = { + * RedRedGain, RedGreenGain, RedBlueGain, + * GreenRedGain, GreenGreenGain, GreenBlueGain, + * BlueRedGain, BlueGreenGain, BlueBlueGain, + * }; + * + * GPU + * ccm = { + * RedRedGain, GreenRedGain, BlueRedGain, + * RedGreenGain, GreenGreenGain, BlueGreenGain, + * RedBlueGain, GreenBlueGain, BlueBlueGain, + * } + * + * However the indexing for the mat data-type is column major hence + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain + * + */ + float rin, gin, bin; + rin = rgb.r; + gin = rgb.g; + bin = rgb.b; + + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + +#elif defined(APPLY_RGB_PARAMETERS) + /* Apply bayer params */ + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; + rgb.g = texture2D(red_param, vec2(rgb.g, 0.5)).g; + rgb.b = texture2D(red_param, vec2(rgb.b, 0.5)).b; +#endif + + gl_FragColor.rgb = rgb; }
Extend out the bayer fragment shaders to take 3 x 256 byte inputs as textures from the CPU. We then use an index to the table to recover the colour-corrected values provided by the SoftIPA thread. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> --- .../internal/shaders/bayer_1x_packed.frag | 56 +++++++++++++++++++ include/libcamera/internal/shaders/bayer_8.frag | 62 +++++++++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-)