mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-20 11:40:10 +01:00
Merge branch 'hk-vk_blend_equation_advanced' into 'main'
asahi/hk: Implement VK_EXT_blend_operation_advanced See merge request mesa/mesa!38929
This commit is contained in:
commit
defb296403
21 changed files with 1156 additions and 267 deletions
|
|
@ -597,7 +597,7 @@ Khronos extensions that are not part of any Vulkan version:
|
|||
VK_EXT_acquire_xlib_display DONE (anv, hk, lvp, nvk, panvk, radv, tu, v3dv, vn)
|
||||
VK_EXT_attachment_feedback_loop_dynamic_state DONE (anv, lvp, radv, tu, vn)
|
||||
VK_EXT_attachment_feedback_loop_layout DONE (anv, hk, lvp, nvk, radv, tu, v3dv, vn)
|
||||
VK_EXT_blend_operation_advanced DONE (vn)
|
||||
VK_EXT_blend_operation_advanced DONE (hk, vn)
|
||||
VK_EXT_border_color_swizzle DONE (anv, hasvk, hk, lvp, nvk, panvk, pvr, radv/gfx10+, tu, v3dv, vn)
|
||||
VK_EXT_buffer_device_address DONE (anv, dzn/sm6.6+, hasvk, hk, nvk, panvk, radv, vn)
|
||||
VK_EXT_calibrated_timestamps DONE (anv, hasvk, hk, kk, nvk, panvk/v10+, lvp, radv, vn, tu/a750+)
|
||||
|
|
|
|||
|
|
@ -100,16 +100,92 @@ struct agx_fs_prolog_key {
|
|||
};
|
||||
|
||||
struct agx_blend_rt_key {
|
||||
unsigned colormask : 4;
|
||||
unsigned advanced_blend : 1;
|
||||
unsigned mode : 26;
|
||||
};
|
||||
static_assert(sizeof(struct agx_blend_rt_key) == 4, "packed");
|
||||
|
||||
struct agx_blend_standard {
|
||||
enum pipe_blend_func rgb_func : 3;
|
||||
enum pipe_blendfactor rgb_src_factor : 5;
|
||||
enum pipe_blendfactor rgb_dst_factor : 5;
|
||||
enum pipe_blend_func alpha_func : 3;
|
||||
enum pipe_blendfactor alpha_src_factor : 5;
|
||||
enum pipe_blendfactor alpha_dst_factor : 5;
|
||||
unsigned colormask : 4;
|
||||
unsigned pad : 2;
|
||||
};
|
||||
static_assert(sizeof(struct agx_blend_rt_key) == 4, "packed");
|
||||
|
||||
static inline unsigned
|
||||
agx_pack_blend_standard(enum pipe_blend_func rgb_func,
|
||||
enum pipe_blendfactor rgb_src_factor,
|
||||
enum pipe_blendfactor rgb_dst_factor,
|
||||
enum pipe_blend_func alpha_func,
|
||||
enum pipe_blendfactor alpha_src_factor,
|
||||
enum pipe_blendfactor alpha_dst_factor)
|
||||
{
|
||||
union {
|
||||
struct agx_blend_standard s;
|
||||
unsigned val;
|
||||
} u = {.s = {
|
||||
.rgb_func = rgb_func,
|
||||
.rgb_src_factor = rgb_src_factor,
|
||||
.rgb_dst_factor = rgb_dst_factor,
|
||||
.alpha_func = alpha_func,
|
||||
.alpha_src_factor = alpha_src_factor,
|
||||
.alpha_dst_factor = alpha_dst_factor,
|
||||
}};
|
||||
|
||||
return u.val;
|
||||
}
|
||||
|
||||
static inline struct agx_blend_standard
|
||||
agx_unpack_blend_standard(unsigned mode)
|
||||
{
|
||||
union {
|
||||
struct agx_blend_standard a;
|
||||
unsigned val;
|
||||
} u = {.val = mode};
|
||||
|
||||
return u.a;
|
||||
}
|
||||
|
||||
struct agx_blend_advanced {
|
||||
enum pipe_advanced_blend_mode op : 8;
|
||||
unsigned overlap : 2;
|
||||
unsigned src_premultiplied : 1;
|
||||
unsigned dst_premultiplied : 1;
|
||||
unsigned clamp_results : 1;
|
||||
};
|
||||
|
||||
static inline unsigned
|
||||
agx_pack_blend_advanced(enum pipe_advanced_blend_mode op, unsigned overlap,
|
||||
bool src_premultiplied, bool dst_premultiplied,
|
||||
bool clamp_results)
|
||||
{
|
||||
union {
|
||||
struct agx_blend_advanced a;
|
||||
unsigned val;
|
||||
} u = {.a = {
|
||||
.op = op,
|
||||
.overlap = overlap,
|
||||
.src_premultiplied = src_premultiplied,
|
||||
.dst_premultiplied = dst_premultiplied,
|
||||
.clamp_results = clamp_results,
|
||||
}};
|
||||
|
||||
return u.val;
|
||||
}
|
||||
|
||||
static inline struct agx_blend_advanced
|
||||
agx_unpack_blend_advanced(unsigned mode)
|
||||
{
|
||||
union {
|
||||
struct agx_blend_advanced a;
|
||||
unsigned val;
|
||||
} u = {.val = mode};
|
||||
|
||||
return u.a;
|
||||
}
|
||||
|
||||
struct agx_blend_key {
|
||||
struct agx_blend_rt_key rt[8];
|
||||
|
|
|
|||
|
|
@ -329,11 +329,14 @@ lower_tests_zs(nir_shader *s, bool value)
|
|||
static inline bool
|
||||
blend_uses_2src(struct agx_blend_rt_key rt)
|
||||
{
|
||||
assert(rt.advanced_blend == false);
|
||||
const struct agx_blend_standard blend = agx_unpack_blend_standard(rt.mode);
|
||||
|
||||
enum pipe_blendfactor factors[] = {
|
||||
rt.rgb_src_factor,
|
||||
rt.rgb_dst_factor,
|
||||
rt.alpha_src_factor,
|
||||
rt.alpha_dst_factor,
|
||||
blend.rgb_src_factor,
|
||||
blend.rgb_dst_factor,
|
||||
blend.alpha_src_factor,
|
||||
blend.alpha_dst_factor,
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(factors); ++i) {
|
||||
|
|
@ -394,7 +397,8 @@ agx_nir_fs_epilog(nir_builder *b, const void *key_)
|
|||
* for blending so should be suppressed for missing attachments to keep
|
||||
* the assert from blowing up on OpenGL.
|
||||
*/
|
||||
if (blend_uses_2src(key->blend.rt[rt]) &&
|
||||
if (!key->blend.rt[rt].advanced_blend &&
|
||||
blend_uses_2src(key->blend.rt[rt]) &&
|
||||
key->rt_formats[rt] != PIPE_FORMAT_NONE) {
|
||||
|
||||
assert(location == 0);
|
||||
|
|
@ -433,18 +437,35 @@ agx_nir_fs_epilog(nir_builder *b, const void *key_)
|
|||
|
||||
for (unsigned i = 0; i < 8; ++i) {
|
||||
opts.format[i] = key->rt_formats[i];
|
||||
opts.rt[i] = (nir_lower_blend_rt){
|
||||
.rgb.src_factor = key->blend.rt[i].rgb_src_factor,
|
||||
.rgb.dst_factor = key->blend.rt[i].rgb_dst_factor,
|
||||
.rgb.func = key->blend.rt[i].rgb_func,
|
||||
if (key->blend.rt[i].advanced_blend) {
|
||||
const struct agx_blend_advanced blend =
|
||||
agx_unpack_blend_advanced(key->blend.rt[i].mode);
|
||||
|
||||
.alpha.src_factor = key->blend.rt[i].alpha_src_factor,
|
||||
.alpha.dst_factor = key->blend.rt[i].alpha_dst_factor,
|
||||
.alpha.func = key->blend.rt[i].alpha_func,
|
||||
opts.rt[i] = (nir_lower_blend_rt){
|
||||
.advanced_blend = true,
|
||||
.colormask = key->blend.rt[i].colormask,
|
||||
.blend_mode = blend.op,
|
||||
.src_premultiplied = blend.src_premultiplied,
|
||||
.dst_premultiplied = blend.dst_premultiplied,
|
||||
.overlap = blend.overlap,
|
||||
};
|
||||
} else {
|
||||
const struct agx_blend_standard blend =
|
||||
agx_unpack_blend_standard(key->blend.rt[i].mode);
|
||||
|
||||
opts.rt[i] = (nir_lower_blend_rt){
|
||||
.rgb.src_factor = blend.rgb_src_factor,
|
||||
.rgb.dst_factor = blend.rgb_dst_factor,
|
||||
.rgb.func = blend.rgb_func,
|
||||
|
||||
.alpha.src_factor = blend.alpha_src_factor,
|
||||
.alpha.dst_factor = blend.alpha_dst_factor,
|
||||
.alpha.func = blend.alpha_func,
|
||||
|
||||
.colormask = key->blend.rt[i].colormask,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* It's more efficient to use masked stores (with
|
||||
* agx_nir_lower_tilebuffer) than to emulate colour masking with
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ hk_cmd_buffer_dirty_render_pass(struct hk_cmd_buffer *cmd)
|
|||
BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_CB_BLEND_ENABLES);
|
||||
BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_CB_BLEND_EQUATIONS);
|
||||
BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_CB_WRITE_MASKS);
|
||||
BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_CB_BLEND_ADVANCED);
|
||||
|
||||
/* These depend on the depth/stencil format */
|
||||
BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_TEST_ENABLE);
|
||||
|
|
@ -2796,7 +2797,7 @@ hk_flush_dynamic_state(struct hk_cmd_buffer *cmd, struct hk_cs *cs,
|
|||
IS_DIRTY(CB_LOGIC_OP_ENABLE) || IS_DIRTY(CB_WRITE_MASKS) ||
|
||||
IS_DIRTY(CB_COLOR_WRITE_ENABLES) || IS_DIRTY(CB_ATTACHMENT_COUNT) ||
|
||||
IS_DIRTY(CB_BLEND_ENABLES) || IS_DIRTY(CB_BLEND_EQUATIONS) ||
|
||||
IS_DIRTY(CB_BLEND_CONSTANTS) ||
|
||||
IS_DIRTY(CB_BLEND_CONSTANTS) || IS_DIRTY(CB_BLEND_ADVANCED) ||
|
||||
desc->root_dirty /* for pipeline stats */ || true) {
|
||||
|
||||
unsigned tib_sample_mask = BITFIELD_MASK(dyn->ms.rasterization_samples);
|
||||
|
|
@ -2890,32 +2891,31 @@ hk_flush_dynamic_state(struct hk_cmd_buffer *cmd, struct hk_cs *cs,
|
|||
if (!dyn->cb.attachments[i].blend_enable) {
|
||||
key.epilog.blend.rt[i] = (struct agx_blend_rt_key){
|
||||
.colormask = write_mask,
|
||||
.rgb_func = PIPE_BLEND_ADD,
|
||||
.alpha_func = PIPE_BLEND_ADD,
|
||||
.rgb_src_factor = PIPE_BLENDFACTOR_ONE,
|
||||
.alpha_src_factor = PIPE_BLENDFACTOR_ONE,
|
||||
.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO,
|
||||
.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO,
|
||||
.mode = agx_pack_blend_standard(
|
||||
PIPE_BLEND_ADD, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO,
|
||||
PIPE_BLEND_ADD, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO),
|
||||
};
|
||||
} else if (cb->color_blend_op >= VK_BLEND_OP_ZERO_EXT) {
|
||||
key.epilog.blend.rt[i] = (struct agx_blend_rt_key){
|
||||
.colormask = write_mask,
|
||||
.advanced_blend = 1,
|
||||
.mode = agx_pack_blend_advanced(
|
||||
vk_advanced_blend_op_to_pipe(cb->color_blend_op),
|
||||
(unsigned int)cb->blend_overlap, cb->src_premultiplied,
|
||||
cb->dst_premultiplied, cb->clamp_results),
|
||||
};
|
||||
|
||||
assert(cb->clamp_results == false);
|
||||
} else {
|
||||
key.epilog.blend.rt[i] = (struct agx_blend_rt_key){
|
||||
.colormask = write_mask,
|
||||
|
||||
.rgb_src_factor =
|
||||
.mode = agx_pack_blend_standard(
|
||||
vk_blend_op_to_pipe(cb->color_blend_op),
|
||||
vk_blend_factor_to_pipe(cb->src_color_blend_factor),
|
||||
|
||||
.rgb_dst_factor =
|
||||
vk_blend_factor_to_pipe(cb->dst_color_blend_factor),
|
||||
|
||||
.rgb_func = vk_blend_op_to_pipe(cb->color_blend_op),
|
||||
|
||||
.alpha_src_factor =
|
||||
vk_blend_op_to_pipe(cb->alpha_blend_op),
|
||||
vk_blend_factor_to_pipe(cb->src_alpha_blend_factor),
|
||||
|
||||
.alpha_dst_factor =
|
||||
vk_blend_factor_to_pipe(cb->dst_alpha_blend_factor),
|
||||
|
||||
.alpha_func = vk_blend_op_to_pipe(cb->alpha_blend_op),
|
||||
vk_blend_factor_to_pipe(cb->dst_alpha_blend_factor)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ hk_get_device_extensions(const struct hk_instance *instance,
|
|||
.KHR_zero_initialize_workgroup_memory = true,
|
||||
.EXT_4444_formats = true,
|
||||
.EXT_attachment_feedback_loop_layout = true,
|
||||
.EXT_blend_operation_advanced = true,
|
||||
.EXT_border_color_swizzle = true,
|
||||
.EXT_buffer_device_address = true,
|
||||
.EXT_calibrated_timestamps = true,
|
||||
|
|
@ -623,6 +624,9 @@ hk_get_device_features(
|
|||
|
||||
/* VK_KHR_shader_relaxed_extended_instruction */
|
||||
.shaderRelaxedExtendedInstruction = true,
|
||||
|
||||
/* VK_EXT_blend_operation_advanced */
|
||||
.advancedBlendCoherentOperations = true,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -996,6 +1000,14 @@ hk_get_device_properties(const struct agx_device *dev,
|
|||
|
||||
/* VK_KHR_fragment_shader_barycentric */
|
||||
.triStripVertexOrderIndependentOfProvokingVertex = false,
|
||||
|
||||
/* VK_EXT_blend_operation_advanced */
|
||||
.advancedBlendMaxColorAttachments = HK_MAX_RTS,
|
||||
.advancedBlendIndependentBlend = true,
|
||||
.advancedBlendNonPremultipliedSrcColor = true,
|
||||
.advancedBlendNonPremultipliedDstColor = true,
|
||||
.advancedBlendCorrelatedOverlap = true,
|
||||
.advancedBlendAllOperations = true,
|
||||
};
|
||||
|
||||
strncpy(properties->deviceName, dev->name, sizeof(properties->deviceName));
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "nir.h"
|
||||
#include "nir_builder.h"
|
||||
#include "nir_blend_equation_advanced_helper.h"
|
||||
#include "gl_nir.h"
|
||||
#include "program/prog_instruction.h"
|
||||
|
||||
|
|
@ -70,123 +71,6 @@ swizzle_w(nir_builder *b, nir_def *src)
|
|||
return nir_channel(b, src, 3);
|
||||
}
|
||||
|
||||
static 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 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 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 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 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 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 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 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 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 nir_def *
|
||||
blend_difference(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
return nir_fabs(b, nir_fsub(b, dst, src));
|
||||
}
|
||||
|
||||
static 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))));
|
||||
}
|
||||
|
||||
/* Return the minimum of a vec3's components */
|
||||
static nir_def *
|
||||
minv3(nir_builder *b, nir_def *v)
|
||||
|
|
@ -303,7 +187,7 @@ set_lum_sat(nir_builder *b,
|
|||
}
|
||||
|
||||
static nir_def *
|
||||
is_mode(nir_builder *b, nir_variable *mode, enum gl_advanced_blend_mode q)
|
||||
is_mode(nir_builder *b, nir_variable *mode, enum pipe_advanced_blend_mode q)
|
||||
{
|
||||
return nir_ieq_imm(b, nir_load_var(b, mode), (unsigned) q);
|
||||
}
|
||||
|
|
@ -318,7 +202,7 @@ calc_blend_result(nir_builder *b,
|
|||
nir_variable *result = add_temp_var(b, "__blend_result", glsl_vec4_type());
|
||||
|
||||
/* If we're not doing advanced blending, just write the original value. */
|
||||
nir_if *if_blending = nir_push_if(b, is_mode(b, mode, BLEND_NONE));
|
||||
nir_if *if_blending = nir_push_if(b, is_mode(b, mode, PIPE_ADVANCED_BLEND_NONE));
|
||||
nir_store_var(b, result, blend_src, ~0);
|
||||
|
||||
nir_push_else(b, if_blending);
|
||||
|
|
@ -362,59 +246,61 @@ calc_blend_result(nir_builder *b,
|
|||
|
||||
unsigned choices = blend_qualifiers;
|
||||
while (choices) {
|
||||
enum gl_advanced_blend_mode choice = (enum gl_advanced_blend_mode)u_bit_scan(&choices);
|
||||
enum pipe_advanced_blend_mode choice = (enum pipe_advanced_blend_mode)u_bit_scan(&choices);
|
||||
|
||||
nir_if *iff = nir_push_if(b, is_mode(b, mode, choice));
|
||||
nir_def *val = NULL;
|
||||
|
||||
switch (choice) {
|
||||
case BLEND_MULTIPLY:
|
||||
case PIPE_ADVANCED_BLEND_MULTIPLY:
|
||||
val = blend_multiply(b, src_rgb_def, dst_rgb_def);
|
||||
break;
|
||||
case BLEND_SCREEN:
|
||||
case PIPE_ADVANCED_BLEND_SCREEN:
|
||||
val = blend_screen(b, src_rgb_def, dst_rgb_def);
|
||||
break;
|
||||
case BLEND_OVERLAY:
|
||||
case PIPE_ADVANCED_BLEND_OVERLAY:
|
||||
val = blend_overlay(b, src_rgb_def, dst_rgb_def);
|
||||
break;
|
||||
case BLEND_DARKEN:
|
||||
case PIPE_ADVANCED_BLEND_DARKEN:
|
||||
val = blend_darken(b, src_rgb_def, dst_rgb_def);
|
||||
break;
|
||||
case BLEND_LIGHTEN:
|
||||
case PIPE_ADVANCED_BLEND_LIGHTEN:
|
||||
val = blend_lighten(b, src_rgb_def, dst_rgb_def);
|
||||
break;
|
||||
case BLEND_COLORDODGE:
|
||||
case PIPE_ADVANCED_BLEND_COLORDODGE:
|
||||
val = blend_colordodge(b, src_rgb_def, dst_rgb_def);
|
||||
break;
|
||||
case BLEND_COLORBURN:
|
||||
case PIPE_ADVANCED_BLEND_COLORBURN:
|
||||
val = blend_colorburn(b, src_rgb_def, dst_rgb_def);
|
||||
break;
|
||||
case BLEND_HARDLIGHT:
|
||||
case PIPE_ADVANCED_BLEND_HARDLIGHT:
|
||||
val = blend_hardlight(b, src_rgb_def, dst_rgb_def);
|
||||
break;
|
||||
case BLEND_SOFTLIGHT:
|
||||
case PIPE_ADVANCED_BLEND_SOFTLIGHT:
|
||||
val = blend_softlight(b, src_rgb_def, dst_rgb_def);
|
||||
break;
|
||||
case BLEND_DIFFERENCE:
|
||||
case PIPE_ADVANCED_BLEND_DIFFERENCE:
|
||||
val = blend_difference(b, src_rgb_def, dst_rgb_def);
|
||||
break;
|
||||
case BLEND_EXCLUSION:
|
||||
case PIPE_ADVANCED_BLEND_EXCLUSION:
|
||||
val = blend_exclusion(b, src_rgb_def, dst_rgb_def);
|
||||
break;
|
||||
case BLEND_HSL_HUE:
|
||||
case PIPE_ADVANCED_BLEND_HSL_HUE:
|
||||
set_lum_sat(b, factor, src_rgb, dst_rgb, dst_rgb);
|
||||
break;
|
||||
case BLEND_HSL_SATURATION:
|
||||
case PIPE_ADVANCED_BLEND_HSL_SATURATION:
|
||||
set_lum_sat(b, factor, dst_rgb, src_rgb, dst_rgb);
|
||||
break;
|
||||
case BLEND_HSL_COLOR:
|
||||
case PIPE_ADVANCED_BLEND_HSL_COLOR:
|
||||
set_lum(b, factor, src_rgb, dst_rgb);
|
||||
break;
|
||||
case BLEND_HSL_LUMINOSITY:
|
||||
case PIPE_ADVANCED_BLEND_HSL_LUMINOSITY:
|
||||
set_lum(b, factor, dst_rgb, src_rgb);
|
||||
break;
|
||||
case BLEND_NONE:
|
||||
case PIPE_ADVANCED_BLEND_NONE:
|
||||
UNREACHABLE("not real cases");
|
||||
default:
|
||||
UNREACHABLE("not supported advanced blend mode");
|
||||
}
|
||||
|
||||
if (val)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "ast.h"
|
||||
#include "glsl_parser_extras.h"
|
||||
#include "compiler/glsl_types.h"
|
||||
#include "util/blend.h"
|
||||
#include "util/u_string.h"
|
||||
#include "util/format/u_format.h"
|
||||
#include "main/consts_exts.h"
|
||||
|
|
@ -1612,22 +1613,22 @@ layout_qualifier_id:
|
|||
const char *s;
|
||||
uint32_t mask;
|
||||
} map[] = {
|
||||
{ "blend_support_multiply", BITFIELD_BIT(BLEND_MULTIPLY) },
|
||||
{ "blend_support_screen", BITFIELD_BIT(BLEND_SCREEN) },
|
||||
{ "blend_support_overlay", BITFIELD_BIT(BLEND_OVERLAY) },
|
||||
{ "blend_support_darken", BITFIELD_BIT(BLEND_DARKEN) },
|
||||
{ "blend_support_lighten", BITFIELD_BIT(BLEND_LIGHTEN) },
|
||||
{ "blend_support_colordodge", BITFIELD_BIT(BLEND_COLORDODGE) },
|
||||
{ "blend_support_colorburn", BITFIELD_BIT(BLEND_COLORBURN) },
|
||||
{ "blend_support_hardlight", BITFIELD_BIT(BLEND_HARDLIGHT) },
|
||||
{ "blend_support_softlight", BITFIELD_BIT(BLEND_SOFTLIGHT) },
|
||||
{ "blend_support_difference", BITFIELD_BIT(BLEND_DIFFERENCE) },
|
||||
{ "blend_support_exclusion", BITFIELD_BIT(BLEND_EXCLUSION) },
|
||||
{ "blend_support_hsl_hue", BITFIELD_BIT(BLEND_HSL_HUE) },
|
||||
{ "blend_support_hsl_saturation", BITFIELD_BIT(BLEND_HSL_SATURATION) },
|
||||
{ "blend_support_hsl_color", BITFIELD_BIT(BLEND_HSL_COLOR) },
|
||||
{ "blend_support_hsl_luminosity", BITFIELD_BIT(BLEND_HSL_LUMINOSITY) },
|
||||
{ "blend_support_all_equations", (1u << (BLEND_HSL_LUMINOSITY + 1)) - 2 },
|
||||
{ "blend_support_multiply", BITFIELD_BIT(PIPE_ADVANCED_BLEND_MULTIPLY) },
|
||||
{ "blend_support_screen", BITFIELD_BIT(PIPE_ADVANCED_BLEND_SCREEN) },
|
||||
{ "blend_support_overlay", BITFIELD_BIT(PIPE_ADVANCED_BLEND_OVERLAY) },
|
||||
{ "blend_support_darken", BITFIELD_BIT(PIPE_ADVANCED_BLEND_DARKEN) },
|
||||
{ "blend_support_lighten", BITFIELD_BIT(PIPE_ADVANCED_BLEND_LIGHTEN) },
|
||||
{ "blend_support_colordodge", BITFIELD_BIT(PIPE_ADVANCED_BLEND_COLORDODGE) },
|
||||
{ "blend_support_colorburn", BITFIELD_BIT(PIPE_ADVANCED_BLEND_COLORBURN) },
|
||||
{ "blend_support_hardlight", BITFIELD_BIT(PIPE_ADVANCED_BLEND_HARDLIGHT) },
|
||||
{ "blend_support_softlight", BITFIELD_BIT(PIPE_ADVANCED_BLEND_SOFTLIGHT) },
|
||||
{ "blend_support_difference", BITFIELD_BIT(PIPE_ADVANCED_BLEND_DIFFERENCE) },
|
||||
{ "blend_support_exclusion", BITFIELD_BIT(PIPE_ADVANCED_BLEND_EXCLUSION) },
|
||||
{ "blend_support_hsl_hue", BITFIELD_BIT(PIPE_ADVANCED_BLEND_HSL_HUE) },
|
||||
{ "blend_support_hsl_saturation", BITFIELD_BIT(PIPE_ADVANCED_BLEND_HSL_SATURATION) },
|
||||
{ "blend_support_hsl_color", BITFIELD_BIT(PIPE_ADVANCED_BLEND_HSL_COLOR) },
|
||||
{ "blend_support_hsl_luminosity", BITFIELD_BIT(PIPE_ADVANCED_BLEND_HSL_LUMINOSITY) },
|
||||
{ "blend_support_all_equations", (1u << (PIPE_ADVANCED_BLEND_HSL_LUMINOSITY + 1)) - 2 },
|
||||
};
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(map); i++) {
|
||||
if (match_layout_qualifier($1, map[i].s, state) == 0) {
|
||||
|
|
|
|||
132
src/compiler/nir/nir_blend_equation_advanced_helper.h
Normal file
132
src/compiler/nir/nir_blend_equation_advanced_helper.h
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* 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))));
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2025 Google LLC
|
||||
* Copyright (C) 2019-2021 Collabora, Ltd.
|
||||
* Copyright (C) 2019 Alyssa Rosenzweig
|
||||
*
|
||||
|
|
@ -33,9 +34,11 @@
|
|||
|
||||
#include "nir_lower_blend.h"
|
||||
#include "compiler/nir/nir.h"
|
||||
#include "compiler/nir/nir_blend_equation_advanced_helper.h"
|
||||
#include "compiler/nir/nir_builder.h"
|
||||
#include "compiler/nir/nir_format_convert.h"
|
||||
#include "util/blend.h"
|
||||
#include "nir_builder_opcodes.h"
|
||||
|
||||
struct ctx {
|
||||
const nir_lower_blend_options *options;
|
||||
|
|
@ -326,6 +329,546 @@ channel_exists(const struct util_format_description *desc, unsigned i)
|
|||
desc->channel[i].type != UTIL_FORMAT_TYPE_VOID;
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
minv3(nir_builder *b, nir_def *v)
|
||||
{
|
||||
return nir_fmin(b, nir_fmin(b, nir_channel(b, v, 0), nir_channel(b, v, 1)),
|
||||
nir_channel(b, v, 2));
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
maxv3(nir_builder *b, nir_def *v)
|
||||
{
|
||||
return nir_fmax(b, nir_fmax(b, nir_channel(b, v, 0), nir_channel(b, v, 1)),
|
||||
nir_channel(b, v, 2));
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
lumv3(nir_builder *b, nir_def *c)
|
||||
{
|
||||
return nir_fdot(b, c, nir_imm_vec3(b, 0.30, 0.59, 0.11));
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
satv3(nir_builder *b, nir_def *c)
|
||||
{
|
||||
return nir_fsub(b, maxv3(b, c), minv3(b, c));
|
||||
}
|
||||
|
||||
/* Clip color to [0,1] while preserving luminosity */
|
||||
static nir_def *
|
||||
clip_color(nir_builder *b, nir_def *c)
|
||||
{
|
||||
nir_def *lum = lumv3(b, c);
|
||||
nir_def *mincol = minv3(b, c);
|
||||
nir_def *maxcol = maxv3(b, c);
|
||||
|
||||
/* If min < 0: c = lum + (c - lum) * lum / (lum - min) */
|
||||
nir_def *t1 = nir_fdiv(b,
|
||||
nir_fmul(b, nir_fsub(b, c, lum), lum),
|
||||
nir_fsub(b, lum, mincol));
|
||||
nir_def *c1 = nir_fadd(b, lum, t1);
|
||||
|
||||
/* If max > 1: c = lum + (c - lum) * (1 - lum) / (max - lum) */
|
||||
nir_def *t2 = nir_fdiv(b,
|
||||
nir_fmul(b, nir_fsub(b, c, lum), nir_fsub_imm(b, 1.0, lum)),
|
||||
nir_fsub(b, maxcol, lum));
|
||||
nir_def *c2 = nir_fadd(b, lum, t2);
|
||||
|
||||
nir_def *min_neg = nir_flt_imm(b, mincol, 0.0);
|
||||
nir_def *max_gt1 = nir_fgt_imm(b, maxcol, 1.0);
|
||||
|
||||
return nir_bcsel(b, min_neg, c1,
|
||||
nir_bcsel(b, max_gt1, c2, c));
|
||||
}
|
||||
|
||||
/* Set luminosity of cbase to match clum */
|
||||
static nir_def *
|
||||
set_lum(nir_builder *b, nir_def *cbase, nir_def *clum)
|
||||
{
|
||||
nir_def *lbase = lumv3(b, cbase);
|
||||
nir_def *llum = lumv3(b, clum);
|
||||
nir_def *diff = nir_fsub(b, llum, lbase);
|
||||
nir_def *c = nir_fadd(b, cbase, diff);
|
||||
|
||||
return clip_color(b, c);
|
||||
}
|
||||
|
||||
/* Set saturation of cbase to match csat, then luminosity to match clum */
|
||||
static nir_def *
|
||||
set_lum_sat(nir_builder *b, nir_def *cbase, nir_def *csat, nir_def *clum)
|
||||
{
|
||||
nir_def *sbase = satv3(b, cbase);
|
||||
nir_def *ssat = satv3(b, csat);
|
||||
nir_def *minbase = minv3(b, cbase);
|
||||
|
||||
/* Scale saturation: (cbase - min) * ssat / sbase */
|
||||
nir_def *scaled = nir_bcsel(b,
|
||||
nir_fgt_imm(b, sbase, 0.0),
|
||||
nir_fdiv(b, nir_fmul(b, nir_fsub(b, cbase, minbase), ssat), sbase),
|
||||
imm3(b, 0.0));
|
||||
|
||||
return set_lum(b, scaled, clum);
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_hsl_hue(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
/* Hue from src, saturation and luminosity from dst */
|
||||
return set_lum_sat(b, src, dst, dst);
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_hsl_saturation(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
/* Saturation from src, hue and luminosity from dst */
|
||||
return set_lum_sat(b, dst, src, dst);
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_hsl_color(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
/* Hue and saturation from src, luminosity from dst */
|
||||
return set_lum(b, src, dst);
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_hsl_luminosity(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
/* Luminosity from src, hue and saturation from dst */
|
||||
return set_lum(b, dst, src);
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_invert(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
return nir_fsub_imm(b, 1.0, dst);
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_invert_rgb(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
return nir_fmul(b, src, nir_fsub_imm(b, 1.0, dst));
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_lineardodge(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
/* min(1, src + dst) */
|
||||
return nir_fmin(b, imm3(b, 1.0), nir_fadd(b, src, dst));
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_linearburn(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
/* max(0, src + dst - 1) */
|
||||
return nir_fmax(b, nir_imm_float(b, 0.0),
|
||||
nir_fadd(b, src, nir_fadd_imm(b, dst, -1.0)));
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_vividlight(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
/*
|
||||
* if src <= 0: 0
|
||||
* if src < 0.5: 1 - min(1, (1-dst) / (2*src))
|
||||
* if src < 1: min(1, dst / (2*(1-src)))
|
||||
* else: 1
|
||||
*/
|
||||
nir_def *two_src = nir_fmul_imm(b, src, 2.0);
|
||||
nir_def *one_minus_dst = nir_fsub_imm(b, 1.0, dst);
|
||||
nir_def *one_minus_src = nir_fsub_imm(b, 1.0, src);
|
||||
|
||||
nir_def *case_lt_half = nir_fsub_imm(b, 1.0,
|
||||
nir_fmin(b, imm3(b, 1.0), nir_fdiv(b, one_minus_dst, two_src)));
|
||||
nir_def *case_lt_one = nir_fmin(b, imm3(b, 1.0),
|
||||
nir_fdiv(b, dst, nir_fmul_imm(b, one_minus_src, 2.0)));
|
||||
|
||||
return nir_bcsel(b, nir_fle_imm(b, src, 0.0), imm3(b, 0.0),
|
||||
nir_bcsel(b, nir_flt_imm(b, src, 0.5), case_lt_half,
|
||||
nir_bcsel(b, nir_flt_imm(b, src, 1.0), case_lt_one,
|
||||
imm3(b, 1.0))));
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_linearlight(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
/*
|
||||
* if 2*src + dst > 2: 1
|
||||
* if 2*src + dst <= 1: 0
|
||||
* else: 2*src + dst - 1
|
||||
*/
|
||||
nir_def *two_src = nir_fmul_imm(b, src, 2.0);
|
||||
nir_def *sum = nir_fadd(b, two_src, dst);
|
||||
nir_def *result = nir_fsub(b, sum, imm3(b, 1.0));
|
||||
|
||||
return nir_bcsel(b, nir_fgt_imm(b, sum, 2.0), imm3(b, 1.0),
|
||||
nir_bcsel(b, nir_fge(b, imm3(b, 1.0), sum), imm3(b, 0.0),
|
||||
result));
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_pinlight(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
/*
|
||||
* if (2*src - 1 > dst) && src < 0.5: 0
|
||||
* if (2*src - 1 > dst) && src >= 0.5: 2*src - 1
|
||||
* if (2*src - 1 <= dst) && src < 0.5*dst: 2*src
|
||||
* if (2*src - 1 <= dst) && src >= 0.5*dst: dst
|
||||
*/
|
||||
nir_def *two_src = nir_fmul_imm(b, src, 2.0);
|
||||
nir_def *two_src_minus_1 = nir_fsub(b, two_src, imm3(b, 1.0));
|
||||
nir_def *half_dst = nir_fmul_imm(b, dst, 0.5);
|
||||
|
||||
nir_def *cond1 = nir_flt(b, dst, two_src_minus_1);
|
||||
nir_def *cond2 = nir_flt_imm(b, src, 0.5);
|
||||
nir_def *cond3 = nir_flt(b, src, half_dst);
|
||||
|
||||
return nir_bcsel(b, cond1,
|
||||
nir_bcsel(b, cond2, imm3(b, 0.0), two_src_minus_1),
|
||||
nir_bcsel(b, cond3, two_src, dst));
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
blend_hardmix(nir_builder *b, nir_def *src, nir_def *dst)
|
||||
{
|
||||
/* if src + dst >= 1: 1, else 0.
|
||||
* Use small epsilon to handle 8-bit quantization.
|
||||
*/
|
||||
nir_def *sum = nir_fadd(b, src, dst);
|
||||
nir_def *threshold = nir_imm_float(b, 1.0 - 0.5 / 255.0); /* ~0.998039 */
|
||||
return nir_bcsel(b, nir_fge(b, sum, threshold),
|
||||
imm3(b, 1.0), imm3(b, 0.0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the blend factor f(Cs', Cd').
|
||||
* Returns NULL for blend modes where X=0, meaning f() is not used.
|
||||
*/
|
||||
static nir_def *
|
||||
calc_blend_factor(nir_builder *b, enum pipe_advanced_blend_mode blend_op, nir_def *src, nir_def *dst)
|
||||
{
|
||||
switch (blend_op) {
|
||||
/* f() result unused (X=0) */
|
||||
case PIPE_ADVANCED_BLEND_NONE:
|
||||
case PIPE_ADVANCED_BLEND_SRC_OUT:
|
||||
case PIPE_ADVANCED_BLEND_DST_OUT:
|
||||
case PIPE_ADVANCED_BLEND_XOR:
|
||||
return NULL;
|
||||
|
||||
/* Standard blend modes */
|
||||
case PIPE_ADVANCED_BLEND_MULTIPLY:
|
||||
return blend_multiply(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_SCREEN:
|
||||
return blend_screen(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_OVERLAY:
|
||||
return blend_overlay(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_DARKEN:
|
||||
return blend_darken(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_LIGHTEN:
|
||||
return blend_lighten(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_COLORDODGE:
|
||||
return blend_colordodge(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_COLORBURN:
|
||||
return blend_colorburn(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_HARDLIGHT:
|
||||
return blend_hardlight(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_SOFTLIGHT:
|
||||
return blend_softlight(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_DIFFERENCE:
|
||||
return blend_difference(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_EXCLUSION:
|
||||
return blend_exclusion(b, src, dst);
|
||||
|
||||
/* HSL blend modes */
|
||||
case PIPE_ADVANCED_BLEND_HSL_HUE:
|
||||
return blend_hsl_hue(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_HSL_SATURATION:
|
||||
return blend_hsl_saturation(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_HSL_COLOR:
|
||||
return blend_hsl_color(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_HSL_LUMINOSITY:
|
||||
return blend_hsl_luminosity(b, src, dst);
|
||||
|
||||
/* Porter-Duff modes where f(Cs,Cd) = Cs or Cd */
|
||||
case PIPE_ADVANCED_BLEND_SRC:
|
||||
case PIPE_ADVANCED_BLEND_SRC_OVER:
|
||||
case PIPE_ADVANCED_BLEND_SRC_IN:
|
||||
case PIPE_ADVANCED_BLEND_SRC_ATOP:
|
||||
return src;
|
||||
case PIPE_ADVANCED_BLEND_DST:
|
||||
case PIPE_ADVANCED_BLEND_DST_OVER:
|
||||
case PIPE_ADVANCED_BLEND_DST_IN:
|
||||
case PIPE_ADVANCED_BLEND_DST_ATOP:
|
||||
return dst;
|
||||
|
||||
/* Extended blend modes */
|
||||
case PIPE_ADVANCED_BLEND_INVERT:
|
||||
return blend_invert(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_INVERT_RGB:
|
||||
return blend_invert_rgb(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_LINEARDODGE:
|
||||
return blend_lineardodge(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_LINEARBURN:
|
||||
return blend_linearburn(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_VIVIDLIGHT:
|
||||
return blend_vividlight(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_LINEARLIGHT:
|
||||
return blend_linearlight(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_PINLIGHT:
|
||||
return blend_pinlight(b, src, dst);
|
||||
case PIPE_ADVANCED_BLEND_HARDMIX:
|
||||
return blend_hardmix(b, src, dst);
|
||||
default:
|
||||
UNREACHABLE("Invalid advanced blend op");
|
||||
}
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
calc_additional_rgb_blend(nir_builder *b, const nir_lower_blend_options *options,
|
||||
unsigned rt,
|
||||
nir_def *src, nir_def *dst)
|
||||
{
|
||||
nir_def *src_rgb = nir_trim_vector(b, src, 3);
|
||||
nir_def *dst_rgb = nir_trim_vector(b, dst, 3);
|
||||
nir_def *src_a = nir_channel(b, src, 3);
|
||||
nir_def *dst_a = nir_channel(b, dst, 3);
|
||||
|
||||
/* Premultiply if non-premultiplied */
|
||||
if (!options->rt[rt].src_premultiplied)
|
||||
src_rgb = nir_fmul(b, src_rgb, src_a);
|
||||
if (!options->rt[rt].dst_premultiplied)
|
||||
dst_rgb = nir_fmul(b, dst_rgb, dst_a);
|
||||
|
||||
nir_def *rgb, *a;
|
||||
|
||||
switch (options->rt[rt].blend_mode) {
|
||||
case PIPE_ADVANCED_BLEND_PLUS:
|
||||
rgb = nir_fadd(b, src_rgb, dst_rgb);
|
||||
a = nir_fadd(b, src_a, dst_a);
|
||||
break;
|
||||
case PIPE_ADVANCED_BLEND_PLUS_CLAMPED:
|
||||
rgb = nir_fmin(b, imm3(b, 1.0), nir_fadd(b, src_rgb, dst_rgb));
|
||||
a = nir_fmin(b, nir_imm_float(b, 1.0), nir_fadd(b, src_a, dst_a));
|
||||
break;
|
||||
case PIPE_ADVANCED_BLEND_PLUS_CLAMPED_ALPHA: {
|
||||
nir_def *max_a = nir_fmin(b, nir_imm_float(b, 1.0), nir_fadd(b, src_a, dst_a));
|
||||
rgb = nir_fmin(b, max_a, nir_fadd(b, src_rgb, dst_rgb));
|
||||
a = max_a;
|
||||
break;
|
||||
}
|
||||
case PIPE_ADVANCED_BLEND_PLUS_DARKER: {
|
||||
nir_def *max_a = nir_fmin(b, nir_imm_float(b, 1.0), nir_fadd(b, src_a, dst_a));
|
||||
/* max(0, max_a - ((src_a - src_rgb) + (dst_a - dst_rgb))) */
|
||||
nir_def *src_diff = nir_fsub(b, src_a, src_rgb);
|
||||
nir_def *dst_diff = nir_fsub(b, dst_a, dst_rgb);
|
||||
rgb = nir_fmax(b, imm3(b, 0.0), nir_fsub(b, max_a, nir_fadd(b, src_diff, dst_diff)));
|
||||
a = max_a;
|
||||
break;
|
||||
}
|
||||
case PIPE_ADVANCED_BLEND_MINUS:
|
||||
rgb = nir_fsub(b, dst_rgb, src_rgb);
|
||||
a = nir_fsub(b, dst_a, src_a);
|
||||
break;
|
||||
case PIPE_ADVANCED_BLEND_MINUS_CLAMPED:
|
||||
rgb = nir_fmax(b, imm3(b, 0.0), nir_fsub(b, dst_rgb, src_rgb));
|
||||
a = nir_fmax(b, nir_imm_float(b, 0.0), nir_fsub(b, dst_a, src_a));
|
||||
break;
|
||||
case PIPE_ADVANCED_BLEND_CONTRAST: {
|
||||
/* res.rgb = (dst_a / 2) + 2 * (dst_rgb - dst_a/2) * (src_rgb - src_a/2) */
|
||||
nir_def *half_dst_a = nir_fmul_imm(b, dst_a, 0.5);
|
||||
nir_def *half_src_a = nir_fmul_imm(b, src_a, 0.5);
|
||||
nir_def *dst_centered = nir_fsub(b, dst_rgb, half_dst_a);
|
||||
nir_def *src_centered = nir_fsub(b, src_rgb, half_src_a);
|
||||
rgb = nir_fadd(b, half_dst_a,
|
||||
nir_fmul_imm(b, nir_fmul(b, dst_centered, src_centered), 2.0));
|
||||
a = dst_a;
|
||||
break;
|
||||
}
|
||||
case PIPE_ADVANCED_BLEND_INVERT_OVG: {
|
||||
/* res.rgb = src_a * (1 - dst_rgb) + (1 - src_a) * dst_rgb */
|
||||
nir_def *one_minus_dst = nir_fsub_imm(b, 1.0, dst_rgb);
|
||||
nir_def *one_minus_src_a = nir_fsub_imm(b, 1.0, src_a);
|
||||
rgb = nir_fadd(b, nir_fmul(b, src_a, one_minus_dst),
|
||||
nir_fmul(b, one_minus_src_a, dst_rgb));
|
||||
a = nir_fsub(b, nir_fadd(b, src_a, dst_a), nir_fmul(b, src_a, dst_a));
|
||||
break;
|
||||
}
|
||||
case PIPE_ADVANCED_BLEND_RED:
|
||||
rgb = nir_vec3(b, nir_channel(b, src_rgb, 0), nir_channel(b, dst_rgb, 1), nir_channel(b, dst_rgb, 2));
|
||||
a = dst_a;
|
||||
break;
|
||||
case PIPE_ADVANCED_BLEND_GREEN:
|
||||
rgb = nir_vec3(b, nir_channel(b, dst_rgb, 0), nir_channel(b, src_rgb, 1), nir_channel(b, dst_rgb, 2));
|
||||
a = dst_a;
|
||||
break;
|
||||
case PIPE_ADVANCED_BLEND_BLUE:
|
||||
rgb = nir_vec3(b, nir_channel(b, dst_rgb, 0), nir_channel(b, dst_rgb, 1), nir_channel(b, src_rgb, 2));
|
||||
a = dst_a;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE("Invalid additional RGB blend op");
|
||||
}
|
||||
|
||||
/* If dst is non-premultiplied, the output should also be non-premultiplied */
|
||||
if (!options->rt[rt].dst_premultiplied) {
|
||||
rgb = nir_bcsel(b,
|
||||
nir_fgt_imm(b, a, 0.0),
|
||||
nir_fdiv(b, rgb, a),
|
||||
imm3(b, 0.0));
|
||||
}
|
||||
|
||||
return nir_vec4(b, nir_channel(b, rgb, 0), nir_channel(b, rgb, 1),
|
||||
nir_channel(b, rgb, 2), a);
|
||||
}
|
||||
|
||||
/*
|
||||
* X, Y, Z blend factors for the advanced blend equation:
|
||||
* RGB = f(Cs',Cd') * X * p0 + Cs' * Y * p1 + Cd' * Z * p2
|
||||
* A = X * p0 + Y * p1 + Z * p2
|
||||
*
|
||||
* Index by enum pipe_advanced_blend_mode.
|
||||
* Modes >= PIPE_ADVANCED_BLEND_PLUS use separate calc_additional_rgb_blend().
|
||||
*/
|
||||
static const float blend_xyz[][3] = {
|
||||
[PIPE_ADVANCED_BLEND_NONE] = { 0, 0, 0 },
|
||||
[PIPE_ADVANCED_BLEND_MULTIPLY] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_SCREEN] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_OVERLAY] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_DARKEN] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_LIGHTEN] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_COLORDODGE] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_COLORBURN] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_HARDLIGHT] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_SOFTLIGHT] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_DIFFERENCE] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_EXCLUSION] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_HSL_HUE] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_HSL_SATURATION] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_HSL_COLOR] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_HSL_LUMINOSITY] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_SRC] = { 1, 1, 0 },
|
||||
[PIPE_ADVANCED_BLEND_DST] = { 1, 0, 1 },
|
||||
[PIPE_ADVANCED_BLEND_SRC_OVER] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_DST_OVER] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_SRC_IN] = { 1, 0, 0 },
|
||||
[PIPE_ADVANCED_BLEND_DST_IN] = { 1, 0, 0 },
|
||||
[PIPE_ADVANCED_BLEND_SRC_OUT] = { 0, 1, 0 },
|
||||
[PIPE_ADVANCED_BLEND_DST_OUT] = { 0, 0, 1 },
|
||||
[PIPE_ADVANCED_BLEND_SRC_ATOP] = { 1, 0, 1 },
|
||||
[PIPE_ADVANCED_BLEND_DST_ATOP] = { 1, 1, 0 },
|
||||
[PIPE_ADVANCED_BLEND_XOR] = { 0, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_INVERT] = { 1, 0, 1 },
|
||||
[PIPE_ADVANCED_BLEND_INVERT_RGB] = { 1, 0, 1 },
|
||||
[PIPE_ADVANCED_BLEND_LINEARDODGE] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_LINEARBURN] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_VIVIDLIGHT] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_LINEARLIGHT] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_PINLIGHT] = { 1, 1, 1 },
|
||||
[PIPE_ADVANCED_BLEND_HARDMIX] = { 1, 1, 1 },
|
||||
};
|
||||
|
||||
static nir_def *
|
||||
nir_blend_advanced(
|
||||
nir_builder *b,
|
||||
const nir_lower_blend_options *options,
|
||||
unsigned rt,
|
||||
nir_def *src, nir_def *dst)
|
||||
{
|
||||
/* Check if this is an additional RGB blend op */
|
||||
if (options->rt[rt].blend_mode >= PIPE_ADVANCED_BLEND_PLUS &&
|
||||
options->rt[rt].blend_mode <= PIPE_ADVANCED_BLEND_BLUE) {
|
||||
return calc_additional_rgb_blend(b, options, rt, src, dst);
|
||||
}
|
||||
|
||||
nir_def *src_rgb = nir_trim_vector(b, src, 3);
|
||||
nir_def *dst_rgb = nir_trim_vector(b, dst, 3);
|
||||
nir_def *src_a = nir_channel(b, src, 3);
|
||||
nir_def *dst_a = nir_channel(b, dst, 3);
|
||||
|
||||
/* Unpremultiply */
|
||||
nir_def *src_rgb_unpre;
|
||||
if (options->rt[rt].src_premultiplied) {
|
||||
src_rgb_unpre = nir_bcsel(b,
|
||||
nir_feq_imm(b, src_a, 0.0),
|
||||
imm3(b, 0.0),
|
||||
nir_fdiv(b, src_rgb, src_a));
|
||||
} else {
|
||||
src_rgb_unpre = src_rgb;
|
||||
}
|
||||
|
||||
nir_def *dst_rgb_unpre;
|
||||
if (options->rt[rt].dst_premultiplied) {
|
||||
dst_rgb_unpre = nir_bcsel(b,
|
||||
nir_feq_imm(b, dst_a, 0.0),
|
||||
imm3(b, 0.0),
|
||||
nir_fdiv(b, dst_rgb, dst_a));
|
||||
} else {
|
||||
dst_rgb_unpre = dst_rgb;
|
||||
}
|
||||
|
||||
/* f(Cs', Cd') - may be NULL if X=0 (result unused) */
|
||||
nir_def *factor = calc_blend_factor(b, options->rt[rt].blend_mode, src_rgb_unpre, dst_rgb_unpre);
|
||||
|
||||
nir_def *p0, *p1, *p2;
|
||||
|
||||
switch (options->rt[rt].overlap) {
|
||||
case 0:
|
||||
/* p0 = As * Ad, p1 = As * (1 - Ad), p2 = Ad * (1 - As) */
|
||||
p0 = nir_fmul(b, src_a, dst_a);
|
||||
p1 = nir_fmul(b, src_a, nir_fsub_imm(b, 1.0, dst_a));
|
||||
p2 = nir_fmul(b, dst_a, nir_fsub_imm(b, 1.0, src_a));
|
||||
break;
|
||||
case 1:
|
||||
/* p0 = max(As + Ad - 1, 0), p1 = min(As, 1 - Ad), p2 = min(Ad, 1 - As) */
|
||||
p0 = nir_fmax(b, nir_fadd_imm(b, nir_fadd(b, src_a, dst_a), -1.0), nir_imm_float(b, 0.0));
|
||||
p1 = nir_fmin(b, src_a, nir_fsub_imm(b, 1.0, dst_a));
|
||||
p2 = nir_fmin(b, dst_a, nir_fsub_imm(b, 1.0, src_a));
|
||||
break;
|
||||
case 2:
|
||||
/* p0 = min(As, Ad), p1 = max(As - Ad, 0), p2 = max(Ad - As, 0) */
|
||||
p0 = nir_fmin(b, src_a, dst_a);
|
||||
p1 = nir_fmax(b, nir_fsub(b, src_a, dst_a), nir_imm_float(b, 0.0));
|
||||
p2 = nir_fmax(b, nir_fsub(b, dst_a, src_a), nir_imm_float(b, 0.0));
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE("unknown overlap");
|
||||
}
|
||||
|
||||
const float x = blend_xyz[options->rt[rt].blend_mode][0];
|
||||
const float y = blend_xyz[options->rt[rt].blend_mode][1];
|
||||
const float z = blend_xyz[options->rt[rt].blend_mode][2];
|
||||
|
||||
/* RGB = f * X * p0 + Cs' * Y * p1 + Cd' * Z * p2 */
|
||||
nir_def *rgb = imm3(b, 0.0);
|
||||
if (factor)
|
||||
rgb = nir_fmul(b, factor, nir_fmul_imm(b, p0, x));
|
||||
if (y != 0.0)
|
||||
rgb = nir_fadd(b, rgb, nir_fmul(b, src_rgb_unpre, nir_fmul_imm(b, p1, y)));
|
||||
if (z != 0.0)
|
||||
rgb = nir_fadd(b, rgb, nir_fmul(b, dst_rgb_unpre, nir_fmul_imm(b, p2, z)));
|
||||
|
||||
/* A = X * p0 + Y * p1 + Z * p2 */
|
||||
nir_def *a = nir_imm_float(b, 0.0);
|
||||
if (x != 0.0)
|
||||
a = nir_fmul_imm(b, p0, x);
|
||||
if (y != 0.0)
|
||||
a = nir_fadd(b, a, nir_fmul_imm(b, p1, y));
|
||||
if (z != 0.0)
|
||||
a = nir_fadd(b, a, nir_fmul_imm(b, p2, z));
|
||||
|
||||
/* If dst is non-premultiplied, the output should also be non-premultiplied */
|
||||
if (!options->rt[rt].dst_premultiplied) {
|
||||
rgb = nir_bcsel(b,
|
||||
nir_fgt_imm(b, a, 0.0),
|
||||
nir_fdiv(b, rgb, a),
|
||||
imm3(b, 0.0));
|
||||
}
|
||||
|
||||
return nir_vec4(b, nir_channel(b, rgb, 0), nir_channel(b, rgb, 1),
|
||||
nir_channel(b, rgb, 2), a);
|
||||
}
|
||||
|
||||
/* Given a blend state, the source color, and the destination color,
|
||||
* return the blended color
|
||||
*/
|
||||
|
|
@ -512,7 +1055,8 @@ nir_lower_blend_instr(nir_builder *b, nir_intrinsic_instr *store, void *data)
|
|||
/* Grab the previous fragment color if we need it */
|
||||
nir_def *dst;
|
||||
|
||||
if (channel_uses_dest(options->rt[rt].rgb) ||
|
||||
if (options->rt[rt].advanced_blend ||
|
||||
channel_uses_dest(options->rt[rt].rgb) ||
|
||||
channel_uses_dest(options->rt[rt].alpha) ||
|
||||
options->logicop_enable ||
|
||||
options->rt[rt].colormask != BITFIELD_MASK(4)) {
|
||||
|
|
@ -530,16 +1074,22 @@ nir_lower_blend_instr(nir_builder *b, nir_intrinsic_instr *store, void *data)
|
|||
dst = nir_undef(b, 4, nir_src_bit_size(store->src[0]));
|
||||
}
|
||||
|
||||
/* Blend the two colors per the passed options. We only call nir_blend if
|
||||
* blending is enabled with a blend mode other than replace (independent of
|
||||
* the color mask). That avoids unnecessary fsat instructions in the common
|
||||
* case where blending is disabled at an API level, but the driver calls
|
||||
/* Blend the two colors per the passed options. Blending is prioritized as:
|
||||
* 1. Logic operations (if logicop_enable is true) - mutually exclusive with blending
|
||||
* 2. Advanced blending (if advanced_blend is set) - uses complex blend equations
|
||||
* 3. Standard blending (if configured) - uses traditional blend factors
|
||||
*
|
||||
* We only call nir_blend if blending is enabled with a blend mode other than replace
|
||||
* (independent of the color mask). That avoids unnecessary fsat instructions in the
|
||||
* common case where blending is disabled at an API level, but the driver calls
|
||||
* nir_blend (possibly for color masking).
|
||||
*/
|
||||
nir_def *blended = src;
|
||||
|
||||
if (options->logicop_enable) {
|
||||
blended = nir_blend_logicop(b, format, logicop_func, src, dst);
|
||||
} else if (options->rt[rt].advanced_blend) {
|
||||
blended = nir_blend_advanced(b, options, rt, src, dst);
|
||||
} else if (!util_format_is_pure_integer(format) &&
|
||||
!nir_blend_replace_rt(&options->rt[rt])) {
|
||||
assert(!util_format_is_scaled(format));
|
||||
|
|
|
|||
|
|
@ -44,7 +44,13 @@ typedef struct {
|
|||
nir_lower_blend_channel alpha;
|
||||
|
||||
/* 4-bit colormask. 0x0 for none, 0xF for RGBA, 0x1 for R */
|
||||
unsigned colormask;
|
||||
unsigned colormask:4;
|
||||
|
||||
unsigned advanced_blend:1;
|
||||
enum pipe_advanced_blend_mode blend_mode;
|
||||
bool src_premultiplied;
|
||||
bool dst_premultiplied;
|
||||
unsigned overlap; /* 0=uncorrelated, 1=conjoint, 2=disjoint */
|
||||
} nir_lower_blend_rt;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
|
|
@ -1255,29 +1255,6 @@ enum gl_access_qualifier
|
|||
ACCESS_FUSED_EU_DISABLE_INTEL = (1 << 19),
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Blend support qualifiers
|
||||
*/
|
||||
enum gl_advanced_blend_mode
|
||||
{
|
||||
BLEND_NONE = 0,
|
||||
BLEND_MULTIPLY,
|
||||
BLEND_SCREEN,
|
||||
BLEND_OVERLAY,
|
||||
BLEND_DARKEN,
|
||||
BLEND_LIGHTEN,
|
||||
BLEND_COLORDODGE,
|
||||
BLEND_COLORBURN,
|
||||
BLEND_HARDLIGHT,
|
||||
BLEND_SOFTLIGHT,
|
||||
BLEND_DIFFERENCE,
|
||||
BLEND_EXCLUSION,
|
||||
BLEND_HSL_HUE,
|
||||
BLEND_HSL_SATURATION,
|
||||
BLEND_HSL_COLOR,
|
||||
BLEND_HSL_LUMINOSITY,
|
||||
};
|
||||
|
||||
enum gl_tess_spacing
|
||||
{
|
||||
TESS_SPACING_UNSPECIFIED,
|
||||
|
|
|
|||
|
|
@ -455,61 +455,62 @@ legal_simple_blend_equation(const struct gl_context *ctx, GLenum mode)
|
|||
}
|
||||
}
|
||||
|
||||
static enum gl_advanced_blend_mode
|
||||
static enum pipe_advanced_blend_mode
|
||||
advanced_blend_mode_from_gl_enum(GLenum mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case GL_MULTIPLY_KHR:
|
||||
return BLEND_MULTIPLY;
|
||||
return PIPE_ADVANCED_BLEND_MULTIPLY;
|
||||
case GL_SCREEN_KHR:
|
||||
return BLEND_SCREEN;
|
||||
return PIPE_ADVANCED_BLEND_SCREEN;
|
||||
case GL_OVERLAY_KHR:
|
||||
return BLEND_OVERLAY;
|
||||
return PIPE_ADVANCED_BLEND_OVERLAY;
|
||||
case GL_DARKEN_KHR:
|
||||
return BLEND_DARKEN;
|
||||
return PIPE_ADVANCED_BLEND_DARKEN;
|
||||
case GL_LIGHTEN_KHR:
|
||||
return BLEND_LIGHTEN;
|
||||
return PIPE_ADVANCED_BLEND_LIGHTEN;
|
||||
case GL_COLORDODGE_KHR:
|
||||
return BLEND_COLORDODGE;
|
||||
return PIPE_ADVANCED_BLEND_COLORDODGE;
|
||||
case GL_COLORBURN_KHR:
|
||||
return BLEND_COLORBURN;
|
||||
return PIPE_ADVANCED_BLEND_COLORBURN;
|
||||
case GL_HARDLIGHT_KHR:
|
||||
return BLEND_HARDLIGHT;
|
||||
return PIPE_ADVANCED_BLEND_HARDLIGHT;
|
||||
case GL_SOFTLIGHT_KHR:
|
||||
return BLEND_SOFTLIGHT;
|
||||
return PIPE_ADVANCED_BLEND_SOFTLIGHT;
|
||||
case GL_DIFFERENCE_KHR:
|
||||
return BLEND_DIFFERENCE;
|
||||
return PIPE_ADVANCED_BLEND_DIFFERENCE;
|
||||
case GL_EXCLUSION_KHR:
|
||||
return BLEND_EXCLUSION;
|
||||
return PIPE_ADVANCED_BLEND_EXCLUSION;
|
||||
case GL_HSL_HUE_KHR:
|
||||
return BLEND_HSL_HUE;
|
||||
return PIPE_ADVANCED_BLEND_HSL_HUE;
|
||||
case GL_HSL_SATURATION_KHR:
|
||||
return BLEND_HSL_SATURATION;
|
||||
return PIPE_ADVANCED_BLEND_HSL_SATURATION;
|
||||
case GL_HSL_COLOR_KHR:
|
||||
return BLEND_HSL_COLOR;
|
||||
return PIPE_ADVANCED_BLEND_HSL_COLOR;
|
||||
case GL_HSL_LUMINOSITY_KHR:
|
||||
return BLEND_HSL_LUMINOSITY;
|
||||
return PIPE_ADVANCED_BLEND_HSL_LUMINOSITY;
|
||||
default:
|
||||
return BLEND_NONE;
|
||||
return PIPE_ADVANCED_BLEND_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If \p mode is one of the advanced blending equations defined by
|
||||
* GL_KHR_blend_equation_advanced (and the extension is supported),
|
||||
* return the corresponding BLEND_* enum. Otherwise, return BLEND_NONE
|
||||
* (which can also be treated as false).
|
||||
* return the corresponding PIPE_ADVANCED_BLEND_* enum.
|
||||
* Otherwise, return PIPE_ADVANCED_BLEND_NONE (which can also be
|
||||
* treated as false).
|
||||
*/
|
||||
static enum gl_advanced_blend_mode
|
||||
static enum pipe_advanced_blend_mode
|
||||
advanced_blend_mode(const struct gl_context *ctx, GLenum mode)
|
||||
{
|
||||
return _mesa_has_KHR_blend_equation_advanced(ctx) ?
|
||||
advanced_blend_mode_from_gl_enum(mode) : BLEND_NONE;
|
||||
advanced_blend_mode_from_gl_enum(mode) : PIPE_ADVANCED_BLEND_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_advanced_blend_mode(struct gl_context *ctx,
|
||||
enum gl_advanced_blend_mode advanced_mode)
|
||||
enum pipe_advanced_blend_mode advanced_mode)
|
||||
{
|
||||
if (ctx->Color._AdvancedBlendMode != advanced_mode) {
|
||||
ctx->Color._AdvancedBlendMode = advanced_mode;
|
||||
|
|
@ -525,7 +526,7 @@ _mesa_BlendEquation( GLenum mode )
|
|||
const unsigned numBuffers = num_buffers(ctx);
|
||||
unsigned buf;
|
||||
bool changed = false;
|
||||
enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode);
|
||||
enum pipe_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode);
|
||||
|
||||
if (MESA_VERBOSE & VERBOSE_API)
|
||||
_mesa_debug(ctx, "glBlendEquation(%s)\n",
|
||||
|
|
@ -575,7 +576,7 @@ _mesa_BlendEquation( GLenum mode )
|
|||
*/
|
||||
static void
|
||||
blend_equationi(struct gl_context *ctx, GLuint buf, GLenum mode,
|
||||
enum gl_advanced_blend_mode advanced_mode)
|
||||
enum pipe_advanced_blend_mode advanced_mode)
|
||||
{
|
||||
if (ctx->Color.Blend[buf].EquationRGB == mode &&
|
||||
ctx->Color.Blend[buf].EquationA == mode)
|
||||
|
|
@ -597,7 +598,7 @@ _mesa_BlendEquationiARB_no_error(GLuint buf, GLenum mode)
|
|||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode);
|
||||
enum pipe_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode);
|
||||
blend_equationi(ctx, buf, mode, advanced_mode);
|
||||
}
|
||||
|
||||
|
|
@ -606,7 +607,7 @@ void GLAPIENTRY
|
|||
_mesa_BlendEquationiARB(GLuint buf, GLenum mode)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode);
|
||||
enum pipe_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode);
|
||||
|
||||
if (MESA_VERBOSE & VERBOSE_API)
|
||||
_mesa_debug(ctx, "glBlendEquationi(%u, %s)\n",
|
||||
|
|
@ -687,7 +688,7 @@ blend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA,
|
|||
ctx->Color.Blend[buf].EquationA = modeA;
|
||||
}
|
||||
ctx->Color._BlendEquationPerBuffer = GL_FALSE;
|
||||
set_advanced_blend_mode(ctx, BLEND_NONE);
|
||||
set_advanced_blend_mode(ctx, PIPE_ADVANCED_BLEND_NONE);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -743,7 +744,7 @@ blend_equation_separatei(struct gl_context *ctx, GLuint buf, GLenum modeRGB,
|
|||
ctx->Color.Blend[buf].EquationRGB = modeRGB;
|
||||
ctx->Color.Blend[buf].EquationA = modeA;
|
||||
ctx->Color._BlendEquationPerBuffer = GL_TRUE;
|
||||
set_advanced_blend_mode(ctx, BLEND_NONE);
|
||||
set_advanced_blend_mode(ctx, PIPE_ADVANCED_BLEND_NONE);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#define BLEND_H
|
||||
|
||||
|
||||
#include "util/blend.h"
|
||||
#include "util/glheader.h"
|
||||
#include "context.h"
|
||||
#include "formats.h"
|
||||
|
|
@ -67,17 +68,17 @@ extern void
|
|||
_mesa_init_color( struct gl_context * ctx );
|
||||
|
||||
|
||||
static inline enum gl_advanced_blend_mode
|
||||
static inline enum pipe_advanced_blend_mode
|
||||
_mesa_get_advanced_blend_sh_constant(GLbitfield blend_enabled,
|
||||
enum gl_advanced_blend_mode mode)
|
||||
enum pipe_advanced_blend_mode mode)
|
||||
{
|
||||
return blend_enabled ? mode : BLEND_NONE;
|
||||
return blend_enabled ? mode : PIPE_ADVANCED_BLEND_NONE;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
_mesa_advanded_blend_sh_constant_changed(struct gl_context *ctx,
|
||||
GLbitfield new_blend_enabled,
|
||||
enum gl_advanced_blend_mode new_mode)
|
||||
enum pipe_advanced_blend_mode new_mode)
|
||||
{
|
||||
return _mesa_get_advanced_blend_sh_constant(new_blend_enabled, new_mode) !=
|
||||
_mesa_get_advanced_blend_sh_constant(ctx->Color.BlendEnabled,
|
||||
|
|
@ -94,7 +95,7 @@ _mesa_flush_vertices_for_blend_state(struct gl_context *ctx)
|
|||
static inline void
|
||||
_mesa_flush_vertices_for_blend_adv(struct gl_context *ctx,
|
||||
GLbitfield new_blend_enabled,
|
||||
enum gl_advanced_blend_mode new_mode)
|
||||
enum pipe_advanced_blend_mode new_mode)
|
||||
{
|
||||
/* The advanced blend mode needs _NEW_COLOR to update the state constant. */
|
||||
if (_mesa_has_KHR_blend_equation_advanced(ctx) &&
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ _mesa_update_valid_to_render_state(struct gl_context *ctx)
|
|||
return;
|
||||
|
||||
if (ctx->Color.BlendEnabled &&
|
||||
ctx->Color._AdvancedBlendMode != BLEND_NONE) {
|
||||
ctx->Color._AdvancedBlendMode != PIPE_ADVANCED_BLEND_NONE) {
|
||||
/* The KHR_blend_equation_advanced spec says:
|
||||
*
|
||||
* "If any non-NONE draw buffer uses a blend equation found in table
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ struct gl_colorbuffer_attrib
|
|||
* draw buffer, and NVX_blend_equation_advanced_multi_draw_buffer still
|
||||
* requires all draw buffers to match, so we only need a single value.
|
||||
*/
|
||||
enum gl_advanced_blend_mode _AdvancedBlendMode;
|
||||
enum pipe_advanced_blend_mode _AdvancedBlendMode;
|
||||
|
||||
/** Coherency requested via glEnable(GL_BLEND_ADVANCED_COHERENT_KHR)? */
|
||||
bool BlendCoherent;
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ st_update_blend( struct st_context *st )
|
|||
blend->rt[i].colormask = colormask;
|
||||
}
|
||||
|
||||
if (ctx->Color._AdvancedBlendMode != BLEND_NONE) {
|
||||
if (ctx->Color._AdvancedBlendMode != PIPE_ADVANCED_BLEND_NONE) {
|
||||
blend->blend_coherent = ctx->Color.BlendCoherent;
|
||||
}
|
||||
|
||||
|
|
@ -272,11 +272,11 @@ st_update_blend( struct st_context *st )
|
|||
blend->logicop_func = ctx->Color._LogicOp;
|
||||
}
|
||||
else if (ctx->Color.BlendEnabled &&
|
||||
ctx->Color._AdvancedBlendMode != BLEND_NONE) {
|
||||
ctx->Color._AdvancedBlendMode != PIPE_ADVANCED_BLEND_NONE) {
|
||||
blend->advanced_blend_func = ctx->Color._AdvancedBlendMode;
|
||||
}
|
||||
else if (ctx->Color.BlendEnabled &&
|
||||
ctx->Color._AdvancedBlendMode == BLEND_NONE) {
|
||||
ctx->Color._AdvancedBlendMode == PIPE_ADVANCED_BLEND_NONE) {
|
||||
/* blending enabled */
|
||||
for (i = 0, j = 0; i < num_state; i++) {
|
||||
if (!(ctx->Color.BlendEnabled & (1 << i)) ||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,57 @@ enum pipe_logicop {
|
|||
PIPE_LOGICOP_SET,
|
||||
};
|
||||
|
||||
enum pipe_advanced_blend_mode {
|
||||
PIPE_ADVANCED_BLEND_NONE = 0,
|
||||
PIPE_ADVANCED_BLEND_MULTIPLY,
|
||||
PIPE_ADVANCED_BLEND_SCREEN,
|
||||
PIPE_ADVANCED_BLEND_OVERLAY,
|
||||
PIPE_ADVANCED_BLEND_DARKEN,
|
||||
PIPE_ADVANCED_BLEND_LIGHTEN,
|
||||
PIPE_ADVANCED_BLEND_COLORDODGE,
|
||||
PIPE_ADVANCED_BLEND_COLORBURN,
|
||||
PIPE_ADVANCED_BLEND_HARDLIGHT,
|
||||
PIPE_ADVANCED_BLEND_SOFTLIGHT,
|
||||
PIPE_ADVANCED_BLEND_DIFFERENCE,
|
||||
PIPE_ADVANCED_BLEND_EXCLUSION,
|
||||
PIPE_ADVANCED_BLEND_HSL_HUE,
|
||||
PIPE_ADVANCED_BLEND_HSL_SATURATION,
|
||||
PIPE_ADVANCED_BLEND_HSL_COLOR,
|
||||
PIPE_ADVANCED_BLEND_HSL_LUMINOSITY,
|
||||
|
||||
/* extra Vulkan only */
|
||||
PIPE_ADVANCED_BLEND_SRC,
|
||||
PIPE_ADVANCED_BLEND_DST,
|
||||
PIPE_ADVANCED_BLEND_SRC_OVER,
|
||||
PIPE_ADVANCED_BLEND_DST_OVER,
|
||||
PIPE_ADVANCED_BLEND_SRC_IN,
|
||||
PIPE_ADVANCED_BLEND_DST_IN,
|
||||
PIPE_ADVANCED_BLEND_SRC_OUT,
|
||||
PIPE_ADVANCED_BLEND_DST_OUT,
|
||||
PIPE_ADVANCED_BLEND_SRC_ATOP,
|
||||
PIPE_ADVANCED_BLEND_DST_ATOP,
|
||||
PIPE_ADVANCED_BLEND_XOR,
|
||||
PIPE_ADVANCED_BLEND_INVERT,
|
||||
PIPE_ADVANCED_BLEND_INVERT_RGB,
|
||||
PIPE_ADVANCED_BLEND_LINEARDODGE,
|
||||
PIPE_ADVANCED_BLEND_LINEARBURN,
|
||||
PIPE_ADVANCED_BLEND_VIVIDLIGHT,
|
||||
PIPE_ADVANCED_BLEND_LINEARLIGHT,
|
||||
PIPE_ADVANCED_BLEND_PINLIGHT,
|
||||
PIPE_ADVANCED_BLEND_HARDMIX,
|
||||
PIPE_ADVANCED_BLEND_PLUS,
|
||||
PIPE_ADVANCED_BLEND_PLUS_CLAMPED,
|
||||
PIPE_ADVANCED_BLEND_PLUS_CLAMPED_ALPHA,
|
||||
PIPE_ADVANCED_BLEND_PLUS_DARKER,
|
||||
PIPE_ADVANCED_BLEND_MINUS,
|
||||
PIPE_ADVANCED_BLEND_MINUS_CLAMPED,
|
||||
PIPE_ADVANCED_BLEND_CONTRAST,
|
||||
PIPE_ADVANCED_BLEND_INVERT_OVG,
|
||||
PIPE_ADVANCED_BLEND_RED,
|
||||
PIPE_ADVANCED_BLEND_GREEN,
|
||||
PIPE_ADVANCED_BLEND_BLUE,
|
||||
};
|
||||
|
||||
/**
|
||||
* When faking RGBX render target formats with RGBA ones, the blender is still
|
||||
* supposed to treat the destination's alpha channel as 1 instead of the
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "vk_blend.h"
|
||||
#include "util/macros.h"
|
||||
#include "vulkan/vulkan_core.h"
|
||||
|
||||
enum pipe_logicop
|
||||
vk_logic_op_to_pipe(VkLogicOp in)
|
||||
|
|
@ -113,3 +114,104 @@ vk_blend_factor_to_pipe(VkBlendFactor vk_factor)
|
|||
UNREACHABLE("Invalid blend factor");
|
||||
}
|
||||
}
|
||||
|
||||
enum pipe_advanced_blend_mode
|
||||
vk_advanced_blend_op_to_pipe(VkBlendOp in)
|
||||
{
|
||||
switch (in) {
|
||||
case VK_BLEND_OP_ZERO_EXT:
|
||||
return PIPE_ADVANCED_BLEND_NONE;
|
||||
case VK_BLEND_OP_MULTIPLY_EXT:
|
||||
return PIPE_ADVANCED_BLEND_MULTIPLY;
|
||||
case VK_BLEND_OP_SCREEN_EXT:
|
||||
return PIPE_ADVANCED_BLEND_SCREEN;
|
||||
case VK_BLEND_OP_OVERLAY_EXT:
|
||||
return PIPE_ADVANCED_BLEND_OVERLAY;
|
||||
case VK_BLEND_OP_DARKEN_EXT:
|
||||
return PIPE_ADVANCED_BLEND_DARKEN;
|
||||
case VK_BLEND_OP_LIGHTEN_EXT:
|
||||
return PIPE_ADVANCED_BLEND_LIGHTEN;
|
||||
case VK_BLEND_OP_COLORDODGE_EXT:
|
||||
return PIPE_ADVANCED_BLEND_COLORDODGE;
|
||||
case VK_BLEND_OP_COLORBURN_EXT:
|
||||
return PIPE_ADVANCED_BLEND_COLORBURN;
|
||||
case VK_BLEND_OP_HARDLIGHT_EXT:
|
||||
return PIPE_ADVANCED_BLEND_HARDLIGHT;
|
||||
case VK_BLEND_OP_SOFTLIGHT_EXT:
|
||||
return PIPE_ADVANCED_BLEND_SOFTLIGHT;
|
||||
case VK_BLEND_OP_DIFFERENCE_EXT:
|
||||
return PIPE_ADVANCED_BLEND_DIFFERENCE;
|
||||
case VK_BLEND_OP_EXCLUSION_EXT:
|
||||
return PIPE_ADVANCED_BLEND_EXCLUSION;
|
||||
case VK_BLEND_OP_HSL_HUE_EXT:
|
||||
return PIPE_ADVANCED_BLEND_HSL_HUE;
|
||||
case VK_BLEND_OP_HSL_SATURATION_EXT:
|
||||
return PIPE_ADVANCED_BLEND_HSL_SATURATION;
|
||||
case VK_BLEND_OP_HSL_COLOR_EXT:
|
||||
return PIPE_ADVANCED_BLEND_HSL_COLOR;
|
||||
case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
|
||||
return PIPE_ADVANCED_BLEND_HSL_LUMINOSITY;
|
||||
case VK_BLEND_OP_SRC_EXT:
|
||||
return PIPE_ADVANCED_BLEND_SRC;
|
||||
case VK_BLEND_OP_DST_EXT:
|
||||
return PIPE_ADVANCED_BLEND_DST;
|
||||
case VK_BLEND_OP_SRC_OVER_EXT:
|
||||
return PIPE_ADVANCED_BLEND_SRC_OVER;
|
||||
case VK_BLEND_OP_DST_OVER_EXT:
|
||||
return PIPE_ADVANCED_BLEND_DST_OVER;
|
||||
case VK_BLEND_OP_SRC_IN_EXT:
|
||||
return PIPE_ADVANCED_BLEND_SRC_IN;
|
||||
case VK_BLEND_OP_DST_IN_EXT:
|
||||
return PIPE_ADVANCED_BLEND_DST_IN;
|
||||
case VK_BLEND_OP_SRC_OUT_EXT:
|
||||
return PIPE_ADVANCED_BLEND_SRC_OUT;
|
||||
case VK_BLEND_OP_DST_OUT_EXT:
|
||||
return PIPE_ADVANCED_BLEND_DST_OUT;
|
||||
case VK_BLEND_OP_SRC_ATOP_EXT:
|
||||
return PIPE_ADVANCED_BLEND_SRC_ATOP;
|
||||
case VK_BLEND_OP_DST_ATOP_EXT:
|
||||
return PIPE_ADVANCED_BLEND_DST_ATOP;
|
||||
case VK_BLEND_OP_XOR_EXT:
|
||||
return PIPE_ADVANCED_BLEND_XOR;
|
||||
case VK_BLEND_OP_INVERT_EXT:
|
||||
return PIPE_ADVANCED_BLEND_INVERT;
|
||||
case VK_BLEND_OP_INVERT_RGB_EXT:
|
||||
return PIPE_ADVANCED_BLEND_INVERT_RGB;
|
||||
case VK_BLEND_OP_LINEARDODGE_EXT:
|
||||
return PIPE_ADVANCED_BLEND_LINEARDODGE;
|
||||
case VK_BLEND_OP_LINEARBURN_EXT:
|
||||
return PIPE_ADVANCED_BLEND_LINEARBURN;
|
||||
case VK_BLEND_OP_VIVIDLIGHT_EXT:
|
||||
return PIPE_ADVANCED_BLEND_VIVIDLIGHT;
|
||||
case VK_BLEND_OP_LINEARLIGHT_EXT:
|
||||
return PIPE_ADVANCED_BLEND_LINEARLIGHT;
|
||||
case VK_BLEND_OP_PINLIGHT_EXT:
|
||||
return PIPE_ADVANCED_BLEND_PINLIGHT;
|
||||
case VK_BLEND_OP_HARDMIX_EXT:
|
||||
return PIPE_ADVANCED_BLEND_HARDMIX;
|
||||
case VK_BLEND_OP_PLUS_EXT:
|
||||
return PIPE_ADVANCED_BLEND_PLUS;
|
||||
case VK_BLEND_OP_PLUS_CLAMPED_EXT:
|
||||
return PIPE_ADVANCED_BLEND_PLUS_CLAMPED;
|
||||
case VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT:
|
||||
return PIPE_ADVANCED_BLEND_PLUS_CLAMPED_ALPHA;
|
||||
case VK_BLEND_OP_PLUS_DARKER_EXT:
|
||||
return PIPE_ADVANCED_BLEND_PLUS_DARKER;
|
||||
case VK_BLEND_OP_MINUS_EXT:
|
||||
return PIPE_ADVANCED_BLEND_MINUS;
|
||||
case VK_BLEND_OP_MINUS_CLAMPED_EXT:
|
||||
return PIPE_ADVANCED_BLEND_MINUS_CLAMPED;
|
||||
case VK_BLEND_OP_CONTRAST_EXT:
|
||||
return PIPE_ADVANCED_BLEND_CONTRAST;
|
||||
case VK_BLEND_OP_INVERT_OVG_EXT:
|
||||
return PIPE_ADVANCED_BLEND_INVERT_OVG;
|
||||
case VK_BLEND_OP_RED_EXT:
|
||||
return PIPE_ADVANCED_BLEND_RED;
|
||||
case VK_BLEND_OP_GREEN_EXT:
|
||||
return PIPE_ADVANCED_BLEND_GREEN;
|
||||
case VK_BLEND_OP_BLUE_EXT:
|
||||
return PIPE_ADVANCED_BLEND_BLUE;
|
||||
default:
|
||||
UNREACHABLE("Invalid advanced blend op");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ extern "C" {
|
|||
enum pipe_logicop vk_logic_op_to_pipe(VkLogicOp in);
|
||||
enum pipe_blend_func vk_blend_op_to_pipe(VkBlendOp in);
|
||||
enum pipe_blendfactor vk_blend_factor_to_pipe(VkBlendFactor in);
|
||||
enum pipe_advanced_blend_mode vk_advanced_blend_op_to_pipe(VkBlendOp in);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ get_dynamic_state_groups(BITSET_WORD *dynamic,
|
|||
BITSET_SET(dynamic, MESA_VK_DYNAMIC_CB_BLEND_EQUATIONS);
|
||||
BITSET_SET(dynamic, MESA_VK_DYNAMIC_CB_WRITE_MASKS);
|
||||
BITSET_SET(dynamic, MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS);
|
||||
BITSET_SET(dynamic, MESA_VK_DYNAMIC_CB_BLEND_ADVANCED);
|
||||
}
|
||||
|
||||
if (groups & MESA_VK_GRAPHICS_STATE_COLOR_ATTACHMENT_MAP_BIT)
|
||||
|
|
@ -177,7 +178,8 @@ fully_dynamic_state_groups(const BITSET_WORD *dynamic)
|
|||
BITSET_TEST(dynamic, MESA_VK_DYNAMIC_CB_BLEND_ENABLES) &&
|
||||
BITSET_TEST(dynamic, MESA_VK_DYNAMIC_CB_BLEND_EQUATIONS) &&
|
||||
BITSET_TEST(dynamic, MESA_VK_DYNAMIC_CB_WRITE_MASKS) &&
|
||||
BITSET_TEST(dynamic, MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS))
|
||||
BITSET_TEST(dynamic, MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS) &&
|
||||
BITSET_TEST(dynamic, MESA_VK_DYNAMIC_CB_BLEND_ADVANCED))
|
||||
groups |= MESA_VK_GRAPHICS_STATE_COLOR_BLEND_BIT;
|
||||
|
||||
if (BITSET_TEST(dynamic, MESA_VK_DYNAMIC_COLOR_ATTACHMENT_MAP))
|
||||
|
|
@ -295,18 +297,17 @@ vk_get_dynamic_graphics_states(BITSET_WORD *dynamic,
|
|||
CASE( DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT, VP_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE)
|
||||
CASE( ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT, ATTACHMENT_FEEDBACK_LOOP_ENABLE)
|
||||
CASE( DEPTH_CLAMP_RANGE_EXT, VP_DEPTH_CLAMP_RANGE)
|
||||
CASE( COLOR_BLEND_ADVANCED_EXT, CB_BLEND_ADVANCED)
|
||||
default:
|
||||
UNREACHABLE("Unsupported dynamic graphics state");
|
||||
}
|
||||
}
|
||||
|
||||
/* attachmentCount is ignored if all of the states using it are dyanmic.
|
||||
*
|
||||
* TODO: Handle advanced blending here when supported.
|
||||
*/
|
||||
/* attachmentCount is ignored if all of the states using it are dyanmic. */
|
||||
if (BITSET_TEST(dynamic, MESA_VK_DYNAMIC_CB_BLEND_ENABLES) &&
|
||||
BITSET_TEST(dynamic, MESA_VK_DYNAMIC_CB_BLEND_EQUATIONS) &&
|
||||
BITSET_TEST(dynamic, MESA_VK_DYNAMIC_CB_WRITE_MASKS))
|
||||
BITSET_TEST(dynamic, MESA_VK_DYNAMIC_CB_WRITE_MASKS) &&
|
||||
BITSET_TEST(dynamic, MESA_VK_DYNAMIC_CB_BLEND_ADVANCED))
|
||||
BITSET_SET(dynamic, MESA_VK_DYNAMIC_CB_ATTACHMENT_COUNT);
|
||||
}
|
||||
|
||||
|
|
@ -1043,6 +1044,24 @@ vk_color_blend_state_init(struct vk_color_blend_state *cb,
|
|||
} else {
|
||||
cb->color_write_enables = BITFIELD_MASK(MESA_VK_MAX_COLOR_ATTACHMENTS);
|
||||
}
|
||||
|
||||
const VkPipelineColorBlendAdvancedStateCreateInfoEXT *advanced =
|
||||
vk_find_struct_const(cb_info->pNext, PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT);
|
||||
if (advanced) {
|
||||
/* Propagate global advanced blend state to per-attachment state */
|
||||
for (uint32_t a = 0; a < cb->attachment_count; a++) {
|
||||
cb->attachments[a].src_premultiplied = advanced->srcPremultiplied;
|
||||
cb->attachments[a].dst_premultiplied = advanced->dstPremultiplied;
|
||||
cb->attachments[a].blend_overlap = advanced->blendOverlap;
|
||||
}
|
||||
} else {
|
||||
/* Vulkan spec defaults */
|
||||
for (uint32_t a = 0; a < cb->attachment_count; a++) {
|
||||
cb->attachments[a].src_premultiplied = true;
|
||||
cb->attachments[a].dst_premultiplied = true;
|
||||
cb->attachments[a].blend_overlap = VK_BLEND_OVERLAP_UNCORRELATED_EXT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* From the description of VkRenderingInputAttachmentIndexInfoKHR:
|
||||
|
|
@ -1128,7 +1147,8 @@ vk_dynamic_graphics_state_init_cb(struct vk_dynamic_graphics_state *dst,
|
|||
|
||||
if (IS_NEEDED(CB_BLEND_ENABLES) ||
|
||||
IS_NEEDED(CB_BLEND_EQUATIONS) ||
|
||||
IS_NEEDED(CB_WRITE_MASKS)) {
|
||||
IS_NEEDED(CB_WRITE_MASKS) ||
|
||||
IS_NEEDED(CB_BLEND_ADVANCED)) {
|
||||
typed_memcpy(dst->cb.attachments, cb->attachments, cb->attachment_count);
|
||||
}
|
||||
|
||||
|
|
@ -2263,6 +2283,17 @@ vk_dynamic_graphics_state_copy(struct vk_dynamic_graphics_state *dst,
|
|||
if (IS_SET_IN_SRC(CB_BLEND_CONSTANTS))
|
||||
COPY_ARRAY(CB_BLEND_CONSTANTS, cb.blend_constants, 4);
|
||||
|
||||
if (IS_SET_IN_SRC(CB_BLEND_ADVANCED)) {
|
||||
for (uint32_t a = 0; a < src->cb.attachment_count; a++) {
|
||||
COPY_MEMBER(CB_BLEND_ADVANCED,
|
||||
cb.attachments[a].dst_premultiplied);
|
||||
COPY_MEMBER(CB_BLEND_ADVANCED,
|
||||
cb.attachments[a].src_premultiplied);
|
||||
COPY_MEMBER(CB_BLEND_ADVANCED,
|
||||
cb.attachments[a].blend_overlap);
|
||||
}
|
||||
}
|
||||
|
||||
COPY_IF_SET(RP_ATTACHMENTS, rp.attachments);
|
||||
|
||||
if (IS_SET_IN_SRC(INPUT_ATTACHMENT_MAP)) {
|
||||
|
|
@ -3085,7 +3116,37 @@ vk_common_CmdSetColorBlendAdvancedEXT(VkCommandBuffer commandBuffer,
|
|||
uint32_t attachmentCount,
|
||||
const VkColorBlendAdvancedEXT* pColorBlendAdvanced)
|
||||
{
|
||||
UNREACHABLE("VK_EXT_blend_operation_advanced unsupported");
|
||||
VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
|
||||
struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
|
||||
|
||||
for (uint32_t i = 0; i < attachmentCount; i++) {
|
||||
uint32_t a = firstAttachment + i;
|
||||
assert(a < ARRAY_SIZE(dyn->cb.attachments));
|
||||
|
||||
SET_DYN_VALUE(dyn, CB_BLEND_ADVANCED,
|
||||
cb.attachments[a].color_blend_op,
|
||||
pColorBlendAdvanced[i].advancedBlendOp);
|
||||
|
||||
SET_DYN_VALUE(dyn, CB_BLEND_ADVANCED,
|
||||
cb.attachments[a].alpha_blend_op,
|
||||
pColorBlendAdvanced[i].advancedBlendOp);
|
||||
|
||||
SET_DYN_VALUE(dyn, CB_BLEND_ADVANCED,
|
||||
cb.attachments[a].src_premultiplied,
|
||||
pColorBlendAdvanced[i].srcPremultiplied);
|
||||
|
||||
SET_DYN_VALUE(dyn, CB_BLEND_ADVANCED,
|
||||
cb.attachments[a].dst_premultiplied,
|
||||
pColorBlendAdvanced[i].dstPremultiplied);
|
||||
|
||||
SET_DYN_VALUE(dyn, CB_BLEND_ADVANCED,
|
||||
cb.attachments[a].blend_overlap,
|
||||
pColorBlendAdvanced[i].blendOverlap);
|
||||
|
||||
SET_DYN_VALUE(dyn, CB_BLEND_ADVANCED,
|
||||
cb.attachments[a].clamp_results,
|
||||
pColorBlendAdvanced[i].clampResults);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3382,6 +3443,7 @@ vk_dynamic_graphic_state_to_str(enum mesa_vk_dynamic_graphics_state state)
|
|||
NAME(CB_BLEND_CONSTANTS);
|
||||
NAME(ATTACHMENT_FEEDBACK_LOOP_ENABLE);
|
||||
NAME(COLOR_ATTACHMENT_MAP);
|
||||
NAME(CB_BLEND_ADVANCED);
|
||||
default: UNREACHABLE("Invalid state");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ enum mesa_vk_dynamic_graphics_state {
|
|||
MESA_VK_DYNAMIC_ATTACHMENT_FEEDBACK_LOOP_ENABLE,
|
||||
MESA_VK_DYNAMIC_COLOR_ATTACHMENT_MAP,
|
||||
MESA_VK_DYNAMIC_INPUT_ATTACHMENT_MAP,
|
||||
MESA_VK_DYNAMIC_CB_BLEND_ADVANCED,
|
||||
|
||||
/* Must be left at the end */
|
||||
MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX,
|
||||
|
|
@ -656,6 +657,15 @@ struct vk_color_blend_attachment_state {
|
|||
* MESA_VK_DYNAMIC_CB_BLEND_EQUATIONS
|
||||
*/
|
||||
VkBlendOp alpha_blend_op;
|
||||
|
||||
/** VkColorBlendAdvancedEXT - advanced blend parameters
|
||||
*
|
||||
* MESA_VK_DYNAMIC_CB_BLEND_ADVANCED
|
||||
*/
|
||||
bool src_premultiplied;
|
||||
bool dst_premultiplied;
|
||||
VkBlendOverlapEXT blend_overlap;
|
||||
bool clamp_results;
|
||||
};
|
||||
|
||||
/***/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue