| Message ID | 20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com |
|---|---|
| State | New |
| Headers | show |
| Series |
|
| Related | show |
On Tue, Apr 07, 2026 at 11:01:05PM +0100, Kieran Bingham wrote: > Move the AWB gains out of the combined matrix and pass > them directly to the EGL shaders. > > Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > --- > src/ipa/simple/algorithms/awb.cpp | 16 +++------------- > src/ipa/simple/ipa_context.h | 5 +---- > src/libcamera/shaders/bayer_1x_packed.frag | 4 ++++ > src/libcamera/shaders/bayer_unpacked.frag | 4 ++++ > src/libcamera/software_isp/debayer_egl.cpp | 5 +++++ > src/libcamera/software_isp/debayer_egl.h | 3 +++ > 6 files changed, 20 insertions(+), 17 deletions(-) > > diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp > index f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 100644 > --- a/src/ipa/simple/algorithms/awb.cpp > +++ b/src/ipa/simple/algorithms/awb.cpp > @@ -38,15 +38,8 @@ void Awb::prepare(IPAContext &context, > DebayerParams *params) > { > auto &gains = context.activeState.awb.gains; > - Matrix<float, 3, 3> gainMatrix = { { gains.r(), 0, 0, > - 0, gains.g(), 0, > - 0, 0, gains.b() } }; > - context.activeState.combinedMatrix = > - gainMatrix * context.activeState.combinedMatrix; The combined matrix is used by the CPU implementation too, aren't you breaking AWB there ? > - > - frameContext.gains.red = gains.r(); > - frameContext.gains.blue = gains.b(); > > + frameContext.gains = gains; > params->gains = gains; > } > > @@ -59,11 +52,8 @@ void Awb::process(IPAContext &context, > const SwIspStats::Histogram &histogram = stats->yHistogram; > const uint8_t blackLevel = context.activeState.blc.level; > > - const float mdGains[] = { > - static_cast<float>(frameContext.gains.red), > - static_cast<float>(frameContext.gains.blue) > - }; > - metadata.set(controls::ColourGains, mdGains); > + metadata.set(controls::ColourGains, { frameContext.gains.r(), > + frameContext.gains.b() }); > > if (!stats->valid) > return; > diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h > index 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 100644 > --- a/src/ipa/simple/ipa_context.h > +++ b/src/ipa/simple/ipa_context.h > @@ -71,10 +71,7 @@ struct IPAFrameContext : public FrameContext { > double gain; > } sensor; > > - struct { > - double red; > - double blue; > - } gains; > + RGB<float> gains; > > float gamma; > std::optional<float> contrast; > diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag > index 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 100644 > --- a/src/libcamera/shaders/bayer_1x_packed.frag > +++ b/src/libcamera/shaders/bayer_1x_packed.frag > @@ -65,6 +65,7 @@ uniform vec2 tex_step; > uniform vec2 tex_bayer_first_red; > > uniform sampler2D tex_y; > +uniform vec3 awb; I'd name this wbGains or colourGains, that's more explicit. Same below. > uniform mat3 ccm; > uniform vec3 blacklevel; > uniform float gamma; > @@ -227,6 +228,9 @@ void main(void) > > rgb = rgb - blacklevel; > > + /* Apply AWB gains, and saturate each channel at sensor range */ > + rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel); > + > /* > * CCM is a 3x3 in the format > * > diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag > index 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 100644 > --- a/src/libcamera/shaders/bayer_unpacked.frag > +++ b/src/libcamera/shaders/bayer_unpacked.frag > @@ -24,6 +24,7 @@ uniform sampler2D tex_y; > varying vec4 center; > varying vec4 yCoord; > varying vec4 xCoord; > +uniform vec3 awb; > uniform mat3 ccm; > uniform vec3 blacklevel; > uniform float gamma; > @@ -130,6 +131,9 @@ void main(void) { > > rgb = rgb - blacklevel; > > + /* Apply AWB gains, and saturate each channel at sensor range */ > + rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel); > + > /* > * CCM is a 3x3 in the format > * > diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp > index 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644 > --- a/src/libcamera/software_isp/debayer_egl.cpp > +++ b/src/libcamera/software_isp/debayer_egl.cpp > @@ -100,6 +100,7 @@ int DebayerEGL::getShaderVariableLocations(void) > attributeTexture_ = glGetAttribLocation(programId_, "textureIn"); > > textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y"); > + awbUniformDataIn_ = glGetUniformLocation(programId_, "awb"); > ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm"); > blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel"); > gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma"); > @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void) > > LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ > << " tex_y " << textureUniformBayerDataIn_ > + << " awb " << awbUniformDataIn_ > << " ccm " << ccmUniformDataIn_ > << " blacklevel " << blackLevelUniformDataIn_ > << " gamma " << gammaUniformDataIn_ > @@ -481,6 +483,9 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) > glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]); > LOG(Debayer, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel; > > + glUniform3f(awbUniformDataIn_, params.gains[0], params.gains[1], params.gains[2]); > + LOG(Debayer, Debug) << " awbUniformDataIn_ " << awbUniformDataIn_ << " data " << params.gains; > + > /* > * Gamma > */ > diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h > index bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644 > --- a/src/libcamera/software_isp/debayer_egl.h > +++ b/src/libcamera/software_isp/debayer_egl.h > @@ -97,6 +97,9 @@ private: > > GLint textureUniformBayerDataIn_; > > + /* Per-frame AWB gains */ All the uniforms below are per-frame parameters, I'd drop the "per-frame". Sorting the members in processing block order (in a separate patch) would make it easier to follow the code. > + GLint awbUniformDataIn_; > + > /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ > GLint ccmUniformDataIn_; > >
diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp index f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 100644 --- a/src/ipa/simple/algorithms/awb.cpp +++ b/src/ipa/simple/algorithms/awb.cpp @@ -38,15 +38,8 @@ void Awb::prepare(IPAContext &context, DebayerParams *params) { auto &gains = context.activeState.awb.gains; - Matrix<float, 3, 3> gainMatrix = { { gains.r(), 0, 0, - 0, gains.g(), 0, - 0, 0, gains.b() } }; - context.activeState.combinedMatrix = - gainMatrix * context.activeState.combinedMatrix; - - frameContext.gains.red = gains.r(); - frameContext.gains.blue = gains.b(); + frameContext.gains = gains; params->gains = gains; } @@ -59,11 +52,8 @@ void Awb::process(IPAContext &context, const SwIspStats::Histogram &histogram = stats->yHistogram; const uint8_t blackLevel = context.activeState.blc.level; - const float mdGains[] = { - static_cast<float>(frameContext.gains.red), - static_cast<float>(frameContext.gains.blue) - }; - metadata.set(controls::ColourGains, mdGains); + metadata.set(controls::ColourGains, { frameContext.gains.r(), + frameContext.gains.b() }); if (!stats->valid) return; diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -71,10 +71,7 @@ struct IPAFrameContext : public FrameContext { double gain; } sensor; - struct { - double red; - double blue; - } gains; + RGB<float> gains; float gamma; std::optional<float> contrast; diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -65,6 +65,7 @@ uniform vec2 tex_step; uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; +uniform vec3 awb; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; @@ -227,6 +228,9 @@ void main(void) rgb = rgb - blacklevel; + /* Apply AWB gains, and saturate each channel at sensor range */ + rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel); + /* * CCM is a 3x3 in the format * diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -24,6 +24,7 @@ uniform sampler2D tex_y; varying vec4 center; varying vec4 yCoord; varying vec4 xCoord; +uniform vec3 awb; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; @@ -130,6 +131,9 @@ void main(void) { rgb = rgb - blacklevel; + /* Apply AWB gains, and saturate each channel at sensor range */ + rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel); + /* * CCM is a 3x3 in the format * diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -100,6 +100,7 @@ int DebayerEGL::getShaderVariableLocations(void) attributeTexture_ = glGetAttribLocation(programId_, "textureIn"); textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y"); + awbUniformDataIn_ = glGetUniformLocation(programId_, "awb"); ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm"); blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel"); gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma"); @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void) LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ << " tex_y " << textureUniformBayerDataIn_ + << " awb " << awbUniformDataIn_ << " ccm " << ccmUniformDataIn_ << " blacklevel " << blackLevelUniformDataIn_ << " gamma " << gammaUniformDataIn_ @@ -481,6 +483,9 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]); LOG(Debayer, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel; + glUniform3f(awbUniformDataIn_, params.gains[0], params.gains[1], params.gains[2]); + LOG(Debayer, Debug) << " awbUniformDataIn_ " << awbUniformDataIn_ << " data " << params.gains; + /* * Gamma */ diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -97,6 +97,9 @@ private: GLint textureUniformBayerDataIn_; + /* Per-frame AWB gains */ + GLint awbUniformDataIn_; + /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ GLint ccmUniformDataIn_;
Move the AWB gains out of the combined matrix and pass them directly to the EGL shaders. Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> --- src/ipa/simple/algorithms/awb.cpp | 16 +++------------- src/ipa/simple/ipa_context.h | 5 +---- src/libcamera/shaders/bayer_1x_packed.frag | 4 ++++ src/libcamera/shaders/bayer_unpacked.frag | 4 ++++ src/libcamera/software_isp/debayer_egl.cpp | 5 +++++ src/libcamera/software_isp/debayer_egl.h | 3 +++ 6 files changed, 20 insertions(+), 17 deletions(-)