mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-19 13:38:19 +02:00
Move the blend equation helper functions (blend_multiply, blend_screen, blend_overlay, etc.) from gl_nir_lower_blend_equation_advanced.c to a new shared header file nir_blend_equation_advanced_helper.h. These helpers implement the mathematical blend operations defined by KHR_blend_equation_advanced and will be reused by the new NIR lowering pass for VK_EXT_blend_operation_advanced. Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38929>
132 lines
4.2 KiB
C
132 lines
4.2 KiB
C
/*
|
|
* Copyright © 2023 Timothy Arceri <tarceri@itsqueeze.com>
|
|
* Copyright © 2016 Intel Corporation
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "nir.h"
|
|
#include "nir_builder.h"
|
|
|
|
static inline nir_def *
|
|
imm3(nir_builder *b, float x)
|
|
{
|
|
return nir_imm_vec3(b, x, x, x);
|
|
}
|
|
|
|
static inline nir_def *
|
|
blend_multiply(nir_builder *b, nir_def *src, nir_def *dst)
|
|
{
|
|
/* f(Cs,Cd) = Cs*Cd */
|
|
return nir_fmul(b, src, dst);
|
|
}
|
|
|
|
static inline nir_def *
|
|
blend_screen(nir_builder *b, nir_def *src, nir_def *dst)
|
|
{
|
|
/* f(Cs,Cd) = Cs+Cd-Cs*Cd */
|
|
return nir_fsub(b, nir_fadd(b, src, dst), nir_fmul(b, src, dst));
|
|
}
|
|
|
|
static inline nir_def *
|
|
blend_overlay(nir_builder *b, nir_def *src, nir_def *dst)
|
|
{
|
|
/* f(Cs,Cd) = 2*Cs*Cd, if Cd <= 0.5
|
|
* 1-2*(1-Cs)*(1-Cd), otherwise
|
|
*/
|
|
nir_def *rule_1 = nir_fmul(b, nir_fmul(b, src, dst), imm3(b, 2.0));
|
|
nir_def *rule_2 =
|
|
nir_fsub(b, imm3(b, 1.0), nir_fmul(b, nir_fmul(b, nir_fsub(b, imm3(b, 1.0), src), nir_fsub(b, imm3(b, 1.0), dst)), imm3(b, 2.0)));
|
|
return nir_bcsel(b, nir_fge(b, imm3(b, 0.5f), dst), rule_1, rule_2);
|
|
}
|
|
static inline nir_def *
|
|
blend_darken(nir_builder *b, nir_def *src, nir_def *dst)
|
|
{
|
|
/* f(Cs,Cd) = min(Cs,Cd) */
|
|
return nir_fmin(b, src, dst);
|
|
}
|
|
|
|
static inline nir_def *
|
|
blend_lighten(nir_builder *b, nir_def *src, nir_def *dst)
|
|
{
|
|
/* f(Cs,Cd) = max(Cs,Cd) */
|
|
return nir_fmax(b, src, dst);
|
|
}
|
|
|
|
static inline nir_def *
|
|
blend_colordodge(nir_builder *b, nir_def *src, nir_def *dst)
|
|
{
|
|
/* f(Cs,Cd) =
|
|
* 0, if Cd <= 0
|
|
* min(1,Cd/(1-Cs)), if Cd > 0 and Cs < 1
|
|
* 1, if Cd > 0 and Cs >= 1
|
|
*/
|
|
return nir_bcsel(b, nir_fge(b, imm3(b, 0.0), dst), imm3(b, 0.0),
|
|
nir_bcsel(b, nir_fge(b, src, imm3(b, 1.0)), imm3(b, 1.0),
|
|
nir_fmin(b, imm3(b, 1.0), nir_fdiv(b, dst, nir_fsub(b, imm3(b, 1.0), src)))));
|
|
}
|
|
|
|
static inline nir_def *
|
|
blend_colorburn(nir_builder *b, nir_def *src, nir_def *dst)
|
|
{
|
|
/* f(Cs,Cd) =
|
|
* 1, if Cd >= 1
|
|
* 1 - min(1,(1-Cd)/Cs), if Cd < 1 and Cs > 0
|
|
* 0, if Cd < 1 and Cs <= 0
|
|
*/
|
|
return nir_bcsel(b, nir_fge(b, dst, imm3(b, 1.0)), imm3(b, 1.0),
|
|
nir_bcsel(b, nir_fge(b, imm3(b, 0.0), src), imm3(b, 0.0),
|
|
nir_fsub(b, imm3(b, 1.0), nir_fmin(b, imm3(b, 1.0), nir_fdiv(b, nir_fsub(b, imm3(b, 1.0), dst), src)))));
|
|
}
|
|
|
|
static inline nir_def *
|
|
blend_hardlight(nir_builder *b, nir_def *src, nir_def *dst)
|
|
{
|
|
/* f(Cs,Cd) = 2*Cs*Cd, if Cs <= 0.5
|
|
* 1-2*(1-Cs)*(1-Cd), otherwise
|
|
*/
|
|
nir_def *rule_1 = nir_fmul(b, imm3(b, 2.0), nir_fmul(b, src, dst));
|
|
nir_def *rule_2 =
|
|
nir_fsub(b, imm3(b, 1.0), nir_fmul(b, imm3(b, 2.0), nir_fmul(b, nir_fsub(b, imm3(b, 1.0), src), nir_fsub(b, imm3(b, 1.0), dst))));
|
|
return nir_bcsel(b, nir_fge(b, imm3(b, 0.5), src), rule_1, rule_2);
|
|
}
|
|
|
|
static inline nir_def *
|
|
blend_softlight(nir_builder *b, nir_def *src, nir_def *dst)
|
|
{
|
|
/* f(Cs,Cd) =
|
|
* Cd-(1-2*Cs)*Cd*(1-Cd),
|
|
* if Cs <= 0.5
|
|
* Cd+(2*Cs-1)*Cd*((16*Cd-12)*Cd+3),
|
|
* if Cs > 0.5 and Cd <= 0.25
|
|
* Cd+(2*Cs-1)*(sqrt(Cd)-Cd),
|
|
* if Cs > 0.5 and Cd > 0.25
|
|
*
|
|
* We can simplify this to
|
|
*
|
|
* f(Cs,Cd) = Cd+(2*Cs-1)*g(Cs,Cd) where
|
|
* g(Cs,Cd) = Cd*Cd-Cd if Cs <= 0.5
|
|
* Cd*((16*Cd-12)*Cd+3) if Cs > 0.5 and Cd <= 0.25
|
|
* sqrt(Cd)-Cd, otherwise
|
|
*/
|
|
nir_def *factor_1 = nir_fmul(b, dst, nir_fsub(b, imm3(b, 1.0), dst));
|
|
nir_def *factor_2 =
|
|
nir_fmul(b, dst, nir_fadd(b, nir_fmul(b, nir_fsub(b, nir_fmul(b, imm3(b, 16.0), dst), imm3(b, 12.0)), dst), imm3(b, 3.0)));
|
|
nir_def *factor_3 = nir_fsub(b, nir_fsqrt(b, dst), dst);
|
|
nir_def *factor = nir_bcsel(b, nir_fge(b, imm3(b, 0.5), src), factor_1,
|
|
nir_bcsel(b, nir_fge(b, imm3(b, 0.25), dst), factor_2, factor_3));
|
|
return nir_fadd(b, dst, nir_fmul(b, nir_fsub(b, nir_fmul(b, imm3(b, 2.0), src), imm3(b, 1.0)), factor));
|
|
}
|
|
|
|
static inline nir_def *
|
|
blend_difference(nir_builder *b, nir_def *src, nir_def *dst)
|
|
{
|
|
return nir_fabs(b, nir_fsub(b, dst, src));
|
|
}
|
|
|
|
static inline nir_def *
|
|
blend_exclusion(nir_builder *b, nir_def *src, nir_def *dst)
|
|
{
|
|
return nir_fadd(b, src, nir_fsub(b, dst, nir_fmul(b, imm3(b, 2.0), nir_fmul(b, src, dst))));
|
|
}
|