|
|
|
@@ -2362,28 +2362,33 @@ generate_fragment(struct llvmpipe_context *lp, |
|
|
|
/* Loop over color outputs / color buffers to do blending. |
|
|
|
*/ |
|
|
|
for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) { |
|
|
|
LLVMValueRef color_ptr; |
|
|
|
LLVMValueRef stride; |
|
|
|
LLVMValueRef index = lp_build_const_int32(gallivm, cbuf); |
|
|
|
if (key->cbuf_format[cbuf] != PIPE_FORMAT_NONE) { |
|
|
|
LLVMValueRef color_ptr; |
|
|
|
LLVMValueRef stride; |
|
|
|
LLVMValueRef index = lp_build_const_int32(gallivm, cbuf); |
|
|
|
|
|
|
|
boolean do_branch = ((key->depth.enabled |
|
|
|
|| key->stencil[0].enabled |
|
|
|
|| key->alpha.enabled) |
|
|
|
&& !shader->info.base.uses_kill); |
|
|
|
boolean do_branch = ((key->depth.enabled |
|
|
|
|| key->stencil[0].enabled |
|
|
|
|| key->alpha.enabled) |
|
|
|
&& !shader->info.base.uses_kill); |
|
|
|
|
|
|
|
color_ptr = LLVMBuildLoad(builder, |
|
|
|
LLVMBuildGEP(builder, color_ptr_ptr, &index, 1, ""), |
|
|
|
""); |
|
|
|
color_ptr = LLVMBuildLoad(builder, |
|
|
|
LLVMBuildGEP(builder, color_ptr_ptr, |
|
|
|
&index, 1, ""), |
|
|
|
""); |
|
|
|
|
|
|
|
lp_build_name(color_ptr, "color_ptr%d", cbuf); |
|
|
|
lp_build_name(color_ptr, "color_ptr%d", cbuf); |
|
|
|
|
|
|
|
stride = LLVMBuildLoad(builder, |
|
|
|
LLVMBuildGEP(builder, stride_ptr, &index, 1, ""), |
|
|
|
""); |
|
|
|
stride = LLVMBuildLoad(builder, |
|
|
|
LLVMBuildGEP(builder, stride_ptr, &index, 1, ""), |
|
|
|
""); |
|
|
|
|
|
|
|
generate_unswizzled_blend(gallivm, cbuf, variant, key->cbuf_format[cbuf], |
|
|
|
num_fs, fs_type, fs_mask, fs_out_color, |
|
|
|
context_ptr, color_ptr, stride, partial_mask, do_branch); |
|
|
|
generate_unswizzled_blend(gallivm, cbuf, variant, |
|
|
|
key->cbuf_format[cbuf], |
|
|
|
num_fs, fs_type, fs_mask, fs_out_color, |
|
|
|
context_ptr, color_ptr, stride, |
|
|
|
partial_mask, do_branch); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
LLVMBuildRetVoid(builder); |
|
|
|
@@ -2901,6 +2906,7 @@ make_variant_key(struct llvmpipe_context *lp, |
|
|
|
|
|
|
|
/* alpha test only applies if render buffer 0 is non-integer (or does not exist) */ |
|
|
|
if (!lp->framebuffer.nr_cbufs || |
|
|
|
!lp->framebuffer.cbufs[0] || |
|
|
|
!util_format_is_pure_integer(lp->framebuffer.cbufs[0]->format)) { |
|
|
|
key->alpha.enabled = lp->depth_stencil->alpha.enabled; |
|
|
|
} |
|
|
|
@@ -2928,64 +2934,74 @@ make_variant_key(struct llvmpipe_context *lp, |
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i < lp->framebuffer.nr_cbufs; i++) { |
|
|
|
enum pipe_format format = lp->framebuffer.cbufs[i]->format; |
|
|
|
struct pipe_rt_blend_state *blend_rt = &key->blend.rt[i]; |
|
|
|
const struct util_format_description *format_desc; |
|
|
|
|
|
|
|
key->cbuf_format[i] = format; |
|
|
|
if (lp->framebuffer.cbufs[i]) { |
|
|
|
enum pipe_format format = lp->framebuffer.cbufs[i]->format; |
|
|
|
const struct util_format_description *format_desc; |
|
|
|
|
|
|
|
/* |
|
|
|
* Figure out if this is a 1d resource. Note that OpenGL allows crazy |
|
|
|
* mixing of 2d textures with height 1 and 1d textures, so make sure |
|
|
|
* we pick 1d if any cbuf or zsbuf is 1d. |
|
|
|
*/ |
|
|
|
if (llvmpipe_resource_is_1d(lp->framebuffer.cbufs[0]->texture)) { |
|
|
|
key->resource_1d = TRUE; |
|
|
|
} |
|
|
|
key->cbuf_format[i] = format; |
|
|
|
|
|
|
|
format_desc = util_format_description(format); |
|
|
|
assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || |
|
|
|
format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB); |
|
|
|
/* |
|
|
|
* Figure out if this is a 1d resource. Note that OpenGL allows crazy |
|
|
|
* mixing of 2d textures with height 1 and 1d textures, so make sure |
|
|
|
* we pick 1d if any cbuf or zsbuf is 1d. |
|
|
|
*/ |
|
|
|
if (llvmpipe_resource_is_1d(lp->framebuffer.cbufs[i]->texture)) { |
|
|
|
key->resource_1d = TRUE; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* Mask out color channels not present in the color buffer. |
|
|
|
*/ |
|
|
|
blend_rt->colormask &= util_format_colormask(format_desc); |
|
|
|
format_desc = util_format_description(format); |
|
|
|
assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || |
|
|
|
format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB); |
|
|
|
|
|
|
|
/* |
|
|
|
* Disable blend for integer formats. |
|
|
|
*/ |
|
|
|
if (util_format_is_pure_integer(format)) { |
|
|
|
blend_rt->blend_enable = 0; |
|
|
|
} |
|
|
|
/* |
|
|
|
* Mask out color channels not present in the color buffer. |
|
|
|
*/ |
|
|
|
blend_rt->colormask &= util_format_colormask(format_desc); |
|
|
|
|
|
|
|
/* |
|
|
|
* Our swizzled render tiles always have an alpha channel, but the linear |
|
|
|
* render target format often does not, so force here the dst alpha to be |
|
|
|
* one. |
|
|
|
* |
|
|
|
* This is not a mere optimization. Wrong results will be produced if the |
|
|
|
* dst alpha is used, the dst format does not have alpha, and the previous |
|
|
|
* rendering was not flushed from the swizzled to linear buffer. For |
|
|
|
* example, NonPowTwo DCT. |
|
|
|
* |
|
|
|
* TODO: This should be generalized to all channels for better |
|
|
|
* performance, but only alpha causes correctness issues. |
|
|
|
* |
|
|
|
* Also, force rgb/alpha func/factors match, to make AoS blending easier. |
|
|
|
*/ |
|
|
|
if (format_desc->swizzle[3] > UTIL_FORMAT_SWIZZLE_W || |
|
|
|
format_desc->swizzle[3] == format_desc->swizzle[0]) { |
|
|
|
/* Doesn't cover mixed snorm/unorm but can't render to them anyway */ |
|
|
|
boolean clamped_zero = !util_format_is_float(format) && |
|
|
|
!util_format_is_snorm(format); |
|
|
|
blend_rt->rgb_src_factor = force_dst_alpha_one(blend_rt->rgb_src_factor, |
|
|
|
clamped_zero); |
|
|
|
blend_rt->rgb_dst_factor = force_dst_alpha_one(blend_rt->rgb_dst_factor, |
|
|
|
clamped_zero); |
|
|
|
blend_rt->alpha_func = blend_rt->rgb_func; |
|
|
|
blend_rt->alpha_src_factor = blend_rt->rgb_src_factor; |
|
|
|
blend_rt->alpha_dst_factor = blend_rt->rgb_dst_factor; |
|
|
|
/* |
|
|
|
* Disable blend for integer formats. |
|
|
|
*/ |
|
|
|
if (util_format_is_pure_integer(format)) { |
|
|
|
blend_rt->blend_enable = 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* Our swizzled render tiles always have an alpha channel, but the |
|
|
|
* linear render target format often does not, so force here the dst |
|
|
|
* alpha to be one. |
|
|
|
* |
|
|
|
* This is not a mere optimization. Wrong results will be produced if |
|
|
|
* the dst alpha is used, the dst format does not have alpha, and the |
|
|
|
* previous rendering was not flushed from the swizzled to linear |
|
|
|
* buffer. For example, NonPowTwo DCT. |
|
|
|
* |
|
|
|
* TODO: This should be generalized to all channels for better |
|
|
|
* performance, but only alpha causes correctness issues. |
|
|
|
* |
|
|
|
* Also, force rgb/alpha func/factors match, to make AoS blending |
|
|
|
* easier. |
|
|
|
*/ |
|
|
|
if (format_desc->swizzle[3] > UTIL_FORMAT_SWIZZLE_W || |
|
|
|
format_desc->swizzle[3] == format_desc->swizzle[0]) { |
|
|
|
/* Doesn't cover mixed snorm/unorm but can't render to them anyway */ |
|
|
|
boolean clamped_zero = !util_format_is_float(format) && |
|
|
|
!util_format_is_snorm(format); |
|
|
|
blend_rt->rgb_src_factor = |
|
|
|
force_dst_alpha_one(blend_rt->rgb_src_factor, clamped_zero); |
|
|
|
blend_rt->rgb_dst_factor = |
|
|
|
force_dst_alpha_one(blend_rt->rgb_dst_factor, clamped_zero); |
|
|
|
blend_rt->alpha_func = blend_rt->rgb_func; |
|
|
|
blend_rt->alpha_src_factor = blend_rt->rgb_src_factor; |
|
|
|
blend_rt->alpha_dst_factor = blend_rt->rgb_dst_factor; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
/* no color buffer for this fragment output */ |
|
|
|
key->cbuf_format[i] = PIPE_FORMAT_NONE; |
|
|
|
blend_rt->colormask = 0x0; |
|
|
|
blend_rt->blend_enable = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|