llvmpipe: implement dual source blending
link up the fs outputs and blend inputs, and make sure the second blend source is correctly loaded and converted (which is quite complex). There's a slight refactoring of the monster generate_unswizzled_blend() function where it makes sense to factor out alpha conversion (which needs to run twice for dual source blend). This passes piglit arb_blend_func_extended tests. v2: remove new but ultimately not used function... Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
@@ -62,6 +62,7 @@ lp_build_blend_aos(struct gallivm_state *gallivm,
|
||||
LLVMValueRef src,
|
||||
LLVMValueRef src_alpha,
|
||||
LLVMValueRef src1,
|
||||
LLVMValueRef src1_alpha,
|
||||
LLVMValueRef dst,
|
||||
LLVMValueRef mask,
|
||||
LLVMValueRef const_,
|
||||
|
||||
@@ -70,6 +70,7 @@ struct lp_build_blend_aos_context
|
||||
LLVMValueRef src;
|
||||
LLVMValueRef src_alpha;
|
||||
LLVMValueRef src1;
|
||||
LLVMValueRef src1_alpha;
|
||||
LLVMValueRef dst;
|
||||
LLVMValueRef const_;
|
||||
LLVMValueRef const_alpha;
|
||||
@@ -94,6 +95,7 @@ lp_build_blend_factor_unswizzled(struct lp_build_blend_aos_context *bld,
|
||||
boolean alpha)
|
||||
{
|
||||
LLVMValueRef src_alpha = bld->src_alpha ? bld->src_alpha : bld->src;
|
||||
LLVMValueRef src1_alpha = bld->src1_alpha ? bld->src1_alpha : bld->src1;
|
||||
LLVMValueRef const_alpha = bld->const_alpha ? bld->const_alpha : bld->const_;
|
||||
|
||||
switch (factor) {
|
||||
@@ -123,8 +125,9 @@ lp_build_blend_factor_unswizzled(struct lp_build_blend_aos_context *bld,
|
||||
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
||||
return const_alpha;
|
||||
case PIPE_BLENDFACTOR_SRC1_COLOR:
|
||||
case PIPE_BLENDFACTOR_SRC1_ALPHA:
|
||||
return bld->src1;
|
||||
case PIPE_BLENDFACTOR_SRC1_ALPHA:
|
||||
return src1_alpha;
|
||||
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
|
||||
if(!bld->inv_src)
|
||||
bld->inv_src = lp_build_comp(&bld->base, bld->src);
|
||||
@@ -147,8 +150,9 @@ lp_build_blend_factor_unswizzled(struct lp_build_blend_aos_context *bld,
|
||||
bld->inv_const_alpha = lp_build_comp(&bld->base, const_alpha);
|
||||
return bld->inv_const_alpha;
|
||||
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
|
||||
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
|
||||
return lp_build_comp(&bld->base, bld->src1);
|
||||
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
|
||||
return lp_build_comp(&bld->base, src1_alpha);
|
||||
default:
|
||||
assert(0);
|
||||
return bld->base.zero;
|
||||
@@ -265,10 +269,13 @@ lp_build_blend_factor(struct lp_build_blend_aos_context *bld,
|
||||
* @param type data type of the pixel vector
|
||||
* @param rt render target index
|
||||
* @param src blend src
|
||||
* @param src_alpha blend src alpha (if not included in src)
|
||||
* @param src1 second blend src (for dual source blend)
|
||||
* @param src1_alpha second blend src alpha (if not included in src1)
|
||||
* @param dst blend dst
|
||||
* @param mask optional mask to apply to the blending result
|
||||
* @param const_ const blend color
|
||||
* @param const_alpha const blend color alpha (if not included in const_)
|
||||
* @param swizzle swizzle values for RGBA
|
||||
*
|
||||
* @return the result of blending src and dst
|
||||
@@ -282,6 +289,7 @@ lp_build_blend_aos(struct gallivm_state *gallivm,
|
||||
LLVMValueRef src,
|
||||
LLVMValueRef src_alpha,
|
||||
LLVMValueRef src1,
|
||||
LLVMValueRef src1_alpha,
|
||||
LLVMValueRef dst,
|
||||
LLVMValueRef mask,
|
||||
LLVMValueRef const_,
|
||||
@@ -307,6 +315,7 @@ lp_build_blend_aos(struct gallivm_state *gallivm,
|
||||
bld.dst = dst;
|
||||
bld.const_ = const_;
|
||||
bld.src_alpha = src_alpha;
|
||||
bld.src1_alpha = src1_alpha;
|
||||
bld.const_alpha = const_alpha;
|
||||
|
||||
/* Find the alpha channel if not provided seperately */
|
||||
|
||||
@@ -115,7 +115,7 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
|
||||
case PIPE_CAP_SM3:
|
||||
return 1;
|
||||
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
|
||||
return 0;
|
||||
return 1;
|
||||
case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
|
||||
return PIPE_MAX_SO_BUFFERS;
|
||||
case PIPE_CAP_ANISOTROPIC_FILTER:
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#include "util/u_dump.h"
|
||||
#include "util/u_string.h"
|
||||
#include "util/u_simple_list.h"
|
||||
#include "util/u_dual_blend.h"
|
||||
#include "os/os_time.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#include "draw/draw_context.h"
|
||||
@@ -247,6 +248,8 @@ generate_fs(struct gallivm_state *gallivm,
|
||||
boolean simple_shader = (shader->info.base.file_count[TGSI_FILE_SAMPLER] == 0 &&
|
||||
shader->info.base.num_inputs < 3 &&
|
||||
shader->info.base.num_instructions < 8);
|
||||
const boolean dual_source_blend = key->blend.rt[0].blend_enable &&
|
||||
util_blend_state_is_dual(&key->blend, 0);
|
||||
unsigned attrib;
|
||||
unsigned chan;
|
||||
unsigned cbuf;
|
||||
@@ -302,6 +305,12 @@ generate_fs(struct gallivm_state *gallivm,
|
||||
color[cbuf][chan] = lp_build_alloca(gallivm, vec_type, "color");
|
||||
}
|
||||
}
|
||||
if (dual_source_blend) {
|
||||
assert(key->nr_cbufs <= 1);
|
||||
for(chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
|
||||
color[1][chan] = lp_build_alloca(gallivm, vec_type, "color1");
|
||||
}
|
||||
}
|
||||
|
||||
/* do triangle edge testing */
|
||||
if (partial_mask) {
|
||||
@@ -414,8 +423,9 @@ generate_fs(struct gallivm_state *gallivm,
|
||||
/* Color write */
|
||||
for (attrib = 0; attrib < shader->info.base.num_outputs; ++attrib)
|
||||
{
|
||||
if (shader->info.base.output_semantic_name[attrib] == TGSI_SEMANTIC_COLOR &&
|
||||
shader->info.base.output_semantic_index[attrib] < key->nr_cbufs)
|
||||
unsigned cbuf = shader->info.base.output_semantic_index[attrib];
|
||||
if ((shader->info.base.output_semantic_name[attrib] == TGSI_SEMANTIC_COLOR) &&
|
||||
((cbuf < key->nr_cbufs) || (cbuf == 1 && dual_source_blend)))
|
||||
{
|
||||
unsigned cbuf = shader->info.base.output_semantic_index[attrib];
|
||||
for(chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
|
||||
@@ -478,6 +488,8 @@ generate_fs_loop(struct gallivm_state *gallivm,
|
||||
boolean simple_shader = (shader->info.base.file_count[TGSI_FILE_SAMPLER] == 0 &&
|
||||
shader->info.base.num_inputs < 3 &&
|
||||
shader->info.base.num_instructions < 8);
|
||||
const boolean dual_source_blend = key->blend.rt[0].blend_enable &&
|
||||
util_blend_state_is_dual(&key->blend, 0);
|
||||
unsigned attrib;
|
||||
unsigned chan;
|
||||
unsigned cbuf;
|
||||
@@ -551,7 +563,15 @@ generate_fs_loop(struct gallivm_state *gallivm,
|
||||
num_loop, "color");
|
||||
}
|
||||
}
|
||||
|
||||
if (dual_source_blend) {
|
||||
assert(key->nr_cbufs <= 1);
|
||||
for(chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
|
||||
out_color[1][chan] = lp_build_array_alloca(gallivm,
|
||||
lp_build_vec_type(gallivm,
|
||||
type),
|
||||
num_loop, "color1");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 'mask' will control execution based on quad's pixel alive/killed state */
|
||||
@@ -656,10 +676,10 @@ generate_fs_loop(struct gallivm_state *gallivm,
|
||||
/* Color write */
|
||||
for (attrib = 0; attrib < shader->info.base.num_outputs; ++attrib)
|
||||
{
|
||||
if (shader->info.base.output_semantic_name[attrib] == TGSI_SEMANTIC_COLOR &&
|
||||
shader->info.base.output_semantic_index[attrib] < key->nr_cbufs)
|
||||
unsigned cbuf = shader->info.base.output_semantic_index[attrib];
|
||||
if ((shader->info.base.output_semantic_name[attrib] == TGSI_SEMANTIC_COLOR) &&
|
||||
((cbuf < key->nr_cbufs) || (cbuf == 1 && dual_source_blend)))
|
||||
{
|
||||
unsigned cbuf = shader->info.base.output_semantic_index[attrib];
|
||||
for(chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
|
||||
if(outputs[attrib][chan]) {
|
||||
/* XXX: just initialize outputs to point at colors[] and
|
||||
@@ -1284,6 +1304,95 @@ convert_from_blend_type(struct gallivm_state *gallivm,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert alpha to same blend type as src
|
||||
*/
|
||||
static void
|
||||
convert_alpha(struct gallivm_state *gallivm,
|
||||
struct lp_type row_type,
|
||||
struct lp_type alpha_type,
|
||||
const unsigned block_size,
|
||||
const unsigned block_height,
|
||||
const unsigned src_count,
|
||||
const unsigned dst_channels,
|
||||
const bool pad_inline,
|
||||
LLVMValueRef* src_alpha)
|
||||
{
|
||||
LLVMBuilderRef builder = gallivm->builder;
|
||||
unsigned i, j;
|
||||
unsigned length = row_type.length;
|
||||
row_type.length = alpha_type.length;
|
||||
|
||||
/* Twiddle the alpha to match pixels */
|
||||
lp_bld_quad_twiddle(gallivm, alpha_type, src_alpha, 4, src_alpha);
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
lp_build_conv(gallivm, alpha_type, row_type, &src_alpha[i], 1, &src_alpha[i], 1);
|
||||
}
|
||||
|
||||
alpha_type = row_type;
|
||||
row_type.length = length;
|
||||
|
||||
/* If only one channel we can only need the single alpha value per pixel */
|
||||
if (src_count == 1) {
|
||||
assert(dst_channels == 1);
|
||||
|
||||
lp_build_concat_n(gallivm, alpha_type, src_alpha, 4, src_alpha, src_count);
|
||||
} else {
|
||||
/* If there are more srcs than rows then we need to split alpha up */
|
||||
if (src_count > block_height) {
|
||||
for (i = src_count; i > 0; --i) {
|
||||
unsigned pixels = block_size / src_count;
|
||||
unsigned idx = i - 1;
|
||||
|
||||
src_alpha[idx] = lp_build_extract_range(gallivm, src_alpha[(idx * pixels) / 4], (idx * pixels) % 4, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is a src for each pixel broadcast the alpha across whole row */
|
||||
if (src_count == block_size) {
|
||||
for (i = 0; i < src_count; ++i) {
|
||||
src_alpha[i] = lp_build_broadcast(gallivm, lp_build_vec_type(gallivm, row_type), src_alpha[i]);
|
||||
}
|
||||
} else {
|
||||
unsigned pixels = block_size / src_count;
|
||||
unsigned channels = pad_inline ? TGSI_NUM_CHANNELS : dst_channels;
|
||||
unsigned alpha_span = 1;
|
||||
LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH];
|
||||
|
||||
/* Check if we need 2 src_alphas for our shuffles */
|
||||
if (pixels > alpha_type.length) {
|
||||
alpha_span = 2;
|
||||
}
|
||||
|
||||
/* Broadcast alpha across all channels, e.g. a1a2 to a1a1a1a1a2a2a2a2 */
|
||||
for (j = 0; j < row_type.length; ++j) {
|
||||
if (j < pixels * channels) {
|
||||
shuffles[j] = lp_build_const_int32(gallivm, j / channels);
|
||||
} else {
|
||||
shuffles[j] = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < src_count; ++i) {
|
||||
unsigned idx1 = i, idx2 = i;
|
||||
|
||||
if (alpha_span > 1){
|
||||
idx1 *= alpha_span;
|
||||
idx2 = idx1 + 1;
|
||||
}
|
||||
|
||||
src_alpha[i] = LLVMBuildShuffleVector(builder,
|
||||
src_alpha[idx1],
|
||||
src_alpha[idx2],
|
||||
LLVMConstVector(shuffles, row_type.length),
|
||||
"");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates the blend function for unswizzled colour buffers
|
||||
* Also generates the read & write from colour buffer
|
||||
@@ -1296,7 +1405,7 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
|
||||
unsigned int num_fs,
|
||||
struct lp_type fs_type,
|
||||
LLVMValueRef* fs_mask,
|
||||
LLVMValueRef fs_out_color[TGSI_NUM_CHANNELS][4],
|
||||
LLVMValueRef fs_out_color[PIPE_MAX_COLOR_BUFS][TGSI_NUM_CHANNELS][4],
|
||||
LLVMValueRef context_ptr,
|
||||
LLVMValueRef color_ptr,
|
||||
LLVMValueRef stride,
|
||||
@@ -1311,9 +1420,12 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
|
||||
|
||||
LLVMBuilderRef builder = gallivm->builder;
|
||||
LLVMValueRef fs_src[4][TGSI_NUM_CHANNELS];
|
||||
LLVMValueRef fs_src1[4][TGSI_NUM_CHANNELS];
|
||||
LLVMValueRef src_alpha[4 * 4];
|
||||
LLVMValueRef src1_alpha[4 * 4];
|
||||
LLVMValueRef src_mask[4 * 4];
|
||||
LLVMValueRef src[4 * 4];
|
||||
LLVMValueRef src1[4 * 4];
|
||||
LLVMValueRef dst[4 * 4];
|
||||
LLVMValueRef blend_color;
|
||||
LLVMValueRef blend_alpha;
|
||||
@@ -1323,14 +1435,13 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
|
||||
struct lp_build_mask_context mask_ctx;
|
||||
struct lp_type mask_type;
|
||||
struct lp_type blend_type;
|
||||
struct lp_type alpha_type;
|
||||
struct lp_type row_type;
|
||||
struct lp_type dst_type;
|
||||
|
||||
unsigned char swizzle[TGSI_NUM_CHANNELS];
|
||||
unsigned vector_width;
|
||||
unsigned src_channels = TGSI_NUM_CHANNELS;
|
||||
unsigned dst_channels;
|
||||
unsigned src_channels;
|
||||
unsigned dst_count;
|
||||
unsigned src_count;
|
||||
unsigned i, j;
|
||||
@@ -1341,8 +1452,9 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
|
||||
|
||||
bool pad_inline = is_arithmetic_format(out_format_desc);
|
||||
bool has_alpha = false;
|
||||
const boolean dual_source_blend = variant->key.blend.rt[0].blend_enable &&
|
||||
util_blend_state_is_dual(&variant->key.blend, 0);
|
||||
|
||||
src_channels = TGSI_NUM_CHANNELS;
|
||||
mask_type = lp_int32_vec4_type();
|
||||
mask_type.length = fs_type.length;
|
||||
|
||||
@@ -1422,17 +1534,20 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
|
||||
*/
|
||||
for (i = 0; i < num_fs; ++i) {
|
||||
/* Always load alpha for use in blending */
|
||||
LLVMValueRef alpha = LLVMBuildLoad(builder, fs_out_color[alpha_channel][i], "");
|
||||
LLVMValueRef alpha = LLVMBuildLoad(builder, fs_out_color[rt][alpha_channel][i], "");
|
||||
|
||||
/* Load each channel */
|
||||
for (j = 0; j < dst_channels; ++j) {
|
||||
fs_src[i][j] = LLVMBuildLoad(builder, fs_out_color[swizzle[j]][i], "");
|
||||
fs_src[i][j] = LLVMBuildLoad(builder, fs_out_color[rt][swizzle[j]][i], "");
|
||||
}
|
||||
|
||||
/* If 3 channels then pad to include alpha for 4 element transpose */
|
||||
/*
|
||||
* XXX If we include that here maybe could actually use it instead of
|
||||
* separate alpha for blending?
|
||||
*/
|
||||
if (dst_channels == 3 && !has_alpha) {
|
||||
fs_src[i][3] = alpha;
|
||||
swizzle[3] = 3;
|
||||
}
|
||||
|
||||
/* We split the row_mask and row_alpha as we want 128bit interleave */
|
||||
@@ -1447,6 +1562,25 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
|
||||
src_alpha[i] = alpha;
|
||||
}
|
||||
}
|
||||
if (dual_source_blend) {
|
||||
/* same as above except different src/dst, skip masks and comments... */
|
||||
for (i = 0; i < num_fs; ++i) {
|
||||
LLVMValueRef alpha = LLVMBuildLoad(builder, fs_out_color[1][alpha_channel][i], "");
|
||||
|
||||
for (j = 0; j < dst_channels; ++j) {
|
||||
fs_src1[i][j] = LLVMBuildLoad(builder, fs_out_color[1][swizzle[j]][i], "");
|
||||
}
|
||||
if (dst_channels == 3 && !has_alpha) {
|
||||
fs_src1[i][3] = alpha;
|
||||
}
|
||||
if (fs_type.length == 8) {
|
||||
src1_alpha[i*2 + 0] = lp_build_extract_range(gallivm, alpha, 0, src_channels);
|
||||
src1_alpha[i*2 + 1] = lp_build_extract_range(gallivm, alpha, src_channels, src_channels);
|
||||
} else {
|
||||
src1_alpha[i] = alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (util_format_is_pure_integer(out_format)) {
|
||||
/*
|
||||
@@ -1467,11 +1601,14 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Pixel twiddle from fragment shader order to memory order
|
||||
*/
|
||||
src_count = generate_fs_twiddle(gallivm, fs_type, num_fs, dst_channels, fs_src, src, pad_inline);
|
||||
if (dual_source_blend) {
|
||||
generate_fs_twiddle(gallivm, fs_type, num_fs, dst_channels, fs_src1, src1, pad_inline);
|
||||
}
|
||||
|
||||
src_channels = dst_channels < 3 ? dst_channels : 4;
|
||||
if (src_count != num_fs * src_channels) {
|
||||
unsigned ds = src_count / (num_fs * src_channels);
|
||||
@@ -1480,12 +1617,17 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
|
||||
}
|
||||
|
||||
blend_type = row_type;
|
||||
alpha_type = fs_type;
|
||||
alpha_type.length = 4;
|
||||
mask_type.length = 4;
|
||||
|
||||
/* Convert src to row_type */
|
||||
src_count = lp_build_conv_auto(gallivm, fs_type, &row_type, src, src_count, src);
|
||||
if (dual_source_blend) {
|
||||
struct lp_type old_row_type = row_type;
|
||||
lp_build_conv_auto(gallivm, fs_type, &row_type, src, src_count, src);
|
||||
src_count = lp_build_conv_auto(gallivm, fs_type, &old_row_type, src1, src_count, src1);
|
||||
}
|
||||
else {
|
||||
src_count = lp_build_conv_auto(gallivm, fs_type, &row_type, src, src_count, src);
|
||||
}
|
||||
|
||||
/* If the rows are not an SSE vector, combine them to become SSE size! */
|
||||
if ((row_type.width * row_type.length) % 128) {
|
||||
@@ -1494,6 +1636,9 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
|
||||
|
||||
dst_count = src_count / (vector_width / bits);
|
||||
combined = lp_build_concat_n(gallivm, row_type, src, src_count, src, dst_count);
|
||||
if (dual_source_blend) {
|
||||
lp_build_concat_n(gallivm, row_type, src1, src_count, src1, dst_count);
|
||||
}
|
||||
|
||||
row_type.length *= combined;
|
||||
src_count /= combined;
|
||||
@@ -1569,75 +1714,17 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
|
||||
* Alpha conversion
|
||||
*/
|
||||
if (!has_alpha) {
|
||||
unsigned length = row_type.length;
|
||||
row_type.length = alpha_type.length;
|
||||
|
||||
/* Twiddle the alpha to match pixels */
|
||||
lp_bld_quad_twiddle(gallivm, alpha_type, src_alpha, 4, src_alpha);
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
lp_build_conv(gallivm, alpha_type, row_type, &src_alpha[i], 1, &src_alpha[i], 1);
|
||||
}
|
||||
|
||||
alpha_type = row_type;
|
||||
row_type.length = length;
|
||||
|
||||
/* If only one channel we can only need the single alpha value per pixel */
|
||||
if (src_count == 1) {
|
||||
assert(dst_channels == 1);
|
||||
|
||||
lp_build_concat_n(gallivm, alpha_type, src_alpha, 4, src_alpha, src_count);
|
||||
} else {
|
||||
/* If there are more srcs than rows then we need to split alpha up */
|
||||
if (src_count > block_height) {
|
||||
for (i = src_count; i > 0; --i) {
|
||||
unsigned pixels = block_size / src_count;
|
||||
unsigned idx = i - 1;
|
||||
|
||||
src_alpha[idx] = lp_build_extract_range(gallivm, src_alpha[(idx * pixels) / 4], (idx * pixels) % 4, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is a src for each pixel broadcast the alpha across whole row */
|
||||
if (src_count == block_size) {
|
||||
for (i = 0; i < src_count; ++i) {
|
||||
src_alpha[i] = lp_build_broadcast(gallivm, lp_build_vec_type(gallivm, row_type), src_alpha[i]);
|
||||
}
|
||||
} else {
|
||||
unsigned pixels = block_size / src_count;
|
||||
unsigned channels = pad_inline ? TGSI_NUM_CHANNELS : dst_channels;
|
||||
unsigned alpha_span = 1;
|
||||
LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH];
|
||||
|
||||
/* Check if we need 2 src_alphas for our shuffles */
|
||||
if (pixels > alpha_type.length) {
|
||||
alpha_span = 2;
|
||||
}
|
||||
|
||||
/* Broadcast alpha across all channels, e.g. a1a2 to a1a1a1a1a2a2a2a2 */
|
||||
for (j = 0; j < row_type.length; ++j) {
|
||||
if (j < pixels * channels) {
|
||||
shuffles[j] = lp_build_const_int32(gallivm, j / channels);
|
||||
} else {
|
||||
shuffles[j] = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < src_count; ++i) {
|
||||
unsigned idx1 = i, idx2 = i;
|
||||
|
||||
if (alpha_span > 1){
|
||||
idx1 *= alpha_span;
|
||||
idx2 = idx1 + 1;
|
||||
}
|
||||
|
||||
src_alpha[i] = LLVMBuildShuffleVector(builder,
|
||||
src_alpha[idx1],
|
||||
src_alpha[idx2],
|
||||
LLVMConstVector(shuffles, row_type.length),
|
||||
"");
|
||||
}
|
||||
}
|
||||
struct lp_type alpha_type = fs_type;
|
||||
alpha_type.length = 4;
|
||||
convert_alpha(gallivm, row_type, alpha_type,
|
||||
block_size, block_height,
|
||||
src_count, dst_channels,
|
||||
pad_inline, src_alpha);
|
||||
if (dual_source_blend) {
|
||||
convert_alpha(gallivm, row_type, alpha_type,
|
||||
block_size, block_height,
|
||||
src_count, dst_channels,
|
||||
pad_inline, src1_alpha);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1693,7 +1780,8 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
|
||||
rt,
|
||||
src[i],
|
||||
has_alpha ? NULL : src_alpha[i],
|
||||
NULL,
|
||||
src1[i],
|
||||
has_alpha ? NULL : src1_alpha[i],
|
||||
dst[i],
|
||||
partial_mask ? src_mask[i] : NULL,
|
||||
blend_color,
|
||||
@@ -1788,6 +1876,8 @@ generate_fragment(struct llvmpipe_context *lp,
|
||||
unsigned cbuf;
|
||||
boolean cbuf0_write_all;
|
||||
boolean try_loop = TRUE;
|
||||
const boolean dual_source_blend = key->blend.rt[0].blend_enable &&
|
||||
util_blend_state_is_dual(&key->blend, 0);
|
||||
|
||||
assert(lp_native_vector_width / 32 >= 4);
|
||||
|
||||
@@ -1951,10 +2041,17 @@ generate_fragment(struct llvmpipe_context *lp,
|
||||
mask_input,
|
||||
thread_data_ptr);
|
||||
|
||||
for (cbuf = 0; cbuf < key->nr_cbufs; cbuf++)
|
||||
for (cbuf = 0; cbuf < key->nr_cbufs; cbuf++) {
|
||||
for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan)
|
||||
fs_out_color[cbuf][chan][i] =
|
||||
out_color[cbuf * !cbuf0_write_all][chan];
|
||||
}
|
||||
if (dual_source_blend) {
|
||||
/* only support one dual source blend target hence always use output 1 */
|
||||
for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan)
|
||||
fs_out_color[1][chan][i] =
|
||||
out_color[1][chan];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -2024,6 +2121,15 @@ generate_fragment(struct llvmpipe_context *lp,
|
||||
fs_out_color[cbuf][chan][i] = ptr;
|
||||
}
|
||||
}
|
||||
if (dual_source_blend) {
|
||||
/* only support one dual source blend target hence always use output 1 */
|
||||
for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
|
||||
ptr = LLVMBuildGEP(builder,
|
||||
color_store[1][chan],
|
||||
&indexi, 1, "");
|
||||
fs_out_color[1][chan][i] = ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2052,7 +2158,7 @@ generate_fragment(struct llvmpipe_context *lp,
|
||||
"");
|
||||
|
||||
generate_unswizzled_blend(gallivm, cbuf, variant, key->cbuf_format[cbuf],
|
||||
num_fs, fs_type, fs_mask, fs_out_color[cbuf],
|
||||
num_fs, fs_type, fs_mask, fs_out_color,
|
||||
context_ptr, color_ptr, stride, partial_mask, do_branch);
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,8 @@ add_blend_test(struct gallivm_state *gallivm,
|
||||
dst = LLVMBuildLoad(builder, dst_ptr, "dst");
|
||||
con = LLVMBuildLoad(builder, const_ptr, "const");
|
||||
|
||||
res = lp_build_blend_aos(gallivm, blend, format, type, rt, src, NULL, src1, dst, NULL, con, NULL, swizzle, 4);
|
||||
res = lp_build_blend_aos(gallivm, blend, format, type, rt, src, NULL,
|
||||
src1, NULL, dst, NULL, con, NULL, swizzle, 4);
|
||||
|
||||
lp_build_name(res, "res");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user