X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_state_setup.c;h=1d79a4ab5282d4028b757d196dd0487adfca2b51;hb=d6fa71fbb0d365cefdabfea9de62cfece71f7486;hp=59ab467fb28ce6befc9778bce57321bc098e5a8e;hpb=473cb3fe4a1bd2e6a271392e41ab121b60889a87;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.c b/src/gallium/drivers/llvmpipe/lp_state_setup.c index 59ab467fb28..1d79a4ab528 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_state_setup.c @@ -50,7 +50,6 @@ #include "lp_state_setup.h" - /* currently organized to interpolate full float[4] attributes even * when some elements are unused. Later, can pack vertex data more * closely. @@ -376,6 +375,19 @@ load_attribute(struct gallivm_state *gallivm, } } +/* + * FIXME: interpolation is always done wrt fb origin (0/0). + * However, if some (small) tri is far away from the origin and gradients + * are large, this can lead to HUGE errors, since the a0 value calculated + * here can get very large (with the actual values inside the triangle way + * smaller), leading to complete loss of accuracy. This could be prevented + * by using some point inside (or at corner) of the tri as interpolation + * origin, or just use barycentric interpolation (which GL suggests and is + * what real hw does - you can get the barycentric coordinates from the + * edge functions in rasterization in principle (though we skip these + * sometimes completely in case of tris covering a block fully, + * which obviously wouldn't work)). + */ static void emit_coef4( struct gallivm_state *gallivm, struct lp_setup_args *args, @@ -385,6 +397,7 @@ emit_coef4( struct gallivm_state *gallivm, LLVMValueRef a2) { LLVMBuilderRef b = gallivm->builder; + LLVMValueRef attr_0; LLVMValueRef dy20_ooa = args->dy20_ooa; LLVMValueRef dy01_ooa = args->dy01_ooa; LLVMValueRef dx20_ooa = args->dx20_ooa; @@ -408,10 +421,10 @@ emit_coef4( struct gallivm_state *gallivm, /* Calculate a0 - the attribute value at the origin */ - LLVMValueRef dadx_x0 = LLVMBuildFMul(b, dadx, x0_center, "dadx_x0"); - LLVMValueRef dady_y0 = LLVMBuildFMul(b, dady, y0_center, "dady_y0"); - LLVMValueRef attr_v0 = LLVMBuildFAdd(b, dadx_x0, dady_y0, "attr_v0"); - LLVMValueRef attr_0 = LLVMBuildFSub(b, a0, attr_v0, "attr_0"); + LLVMValueRef dadx_x0 = LLVMBuildFMul(b, dadx, x0_center, "dadx_x0"); + LLVMValueRef dady_y0 = LLVMBuildFMul(b, dady, y0_center, "dady_y0"); + LLVMValueRef attr_v0 = LLVMBuildFAdd(b, dadx_x0, dady_y0, "attr_v0"); + attr_0 = LLVMBuildFSub(b, a0, attr_v0, "attr_0"); store_coef(gallivm, args, slot, attr_0, dadx, dady); } @@ -623,7 +636,7 @@ init_args(struct gallivm_state *gallivm, LLVMValueRef zeroi = lp_build_const_int32(gallivm, 0); LLVMValueRef pixel_center, xy0_center, dxy01, dxy20, dyx20; LLVMValueRef e, f, ef, ooa; - LLVMValueRef shuffles[4]; + LLVMValueRef shuffles[4], shuf10; LLVMValueRef attr_pos[3]; struct lp_type typef4 = lp_type_float_vec(32, 128); struct lp_build_context bld; @@ -651,8 +664,9 @@ init_args(struct gallivm_state *gallivm, shuffles[1] = zeroi; shuffles[2] = LLVMGetUndef(shuf_type); shuffles[3] = LLVMGetUndef(shuf_type); + shuf10 = LLVMConstVector(shuffles, 4); - dyx20 = LLVMBuildShuffleVector(b, dxy20, dxy20, LLVMConstVector(shuffles, 4), ""); + dyx20 = LLVMBuildShuffleVector(b, dxy20, dxy20, shuf10, ""); ef = LLVMBuildFMul(b, dxy01, dyx20, "ef"); e = LLVMBuildExtractElement(b, ef, zeroi, "");