Path: blob/21.2-virgl/src/gallium/auxiliary/gallivm/lp_bld_quad.c
4565 views
/**************************************************************************1*2* Copyright 2010 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL16* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,17* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR18* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE19* USE OR OTHER DEALINGS IN THE SOFTWARE.20*21* The above copyright notice and this permission notice (including the22* next paragraph) shall be included in all copies or substantial portions23* of the Software.24*25**************************************************************************/262728#include "lp_bld_type.h"29#include "lp_bld_arit.h"30#include "lp_bld_const.h"31#include "lp_bld_swizzle.h"32#include "lp_bld_quad.h"33#include "lp_bld_pack.h"343536static const unsigned char37swizzle_left[4] = {38LP_BLD_QUAD_TOP_LEFT, LP_BLD_QUAD_TOP_LEFT,39LP_BLD_QUAD_BOTTOM_LEFT, LP_BLD_QUAD_BOTTOM_LEFT40};4142static const unsigned char43swizzle_right[4] = {44LP_BLD_QUAD_TOP_RIGHT, LP_BLD_QUAD_TOP_RIGHT,45LP_BLD_QUAD_BOTTOM_RIGHT, LP_BLD_QUAD_BOTTOM_RIGHT46};4748static const unsigned char49swizzle_top[4] = {50LP_BLD_QUAD_TOP_LEFT, LP_BLD_QUAD_TOP_RIGHT,51LP_BLD_QUAD_TOP_LEFT, LP_BLD_QUAD_TOP_RIGHT52};5354static const unsigned char55swizzle_bottom[4] = {56LP_BLD_QUAD_BOTTOM_LEFT, LP_BLD_QUAD_BOTTOM_RIGHT,57LP_BLD_QUAD_BOTTOM_LEFT, LP_BLD_QUAD_BOTTOM_RIGHT58};596061LLVMValueRef62lp_build_ddx(struct lp_build_context *bld,63LLVMValueRef a)64{65LLVMValueRef a_left = lp_build_swizzle_aos(bld, a, swizzle_left);66LLVMValueRef a_right = lp_build_swizzle_aos(bld, a, swizzle_right);67return lp_build_sub(bld, a_right, a_left);68}697071LLVMValueRef72lp_build_ddy(struct lp_build_context *bld,73LLVMValueRef a)74{75LLVMValueRef a_top = lp_build_swizzle_aos(bld, a, swizzle_top);76LLVMValueRef a_bottom = lp_build_swizzle_aos(bld, a, swizzle_bottom);77return lp_build_sub(bld, a_bottom, a_top);78}7980/*81* Helper for building packed ddx/ddy vector for one coord (scalar per quad82* values). The vector will look like this (8-wide):83* dr1dx _____ -dr1dy _____ dr2dx _____ -dr2dy _____84* This only requires one shuffle instead of two for more straightforward packing.85*/86LLVMValueRef87lp_build_packed_ddx_ddy_onecoord(struct lp_build_context *bld,88LLVMValueRef a)89{90struct gallivm_state *gallivm = bld->gallivm;91LLVMBuilderRef builder = gallivm->builder;92LLVMValueRef vec1, vec2;9394/* use aos swizzle helper */9596static const unsigned char swizzle1[] = { /* no-op swizzle */97LP_BLD_QUAD_TOP_LEFT, LP_BLD_SWIZZLE_DONTCARE,98LP_BLD_QUAD_BOTTOM_LEFT, LP_BLD_SWIZZLE_DONTCARE99};100static const unsigned char swizzle2[] = {101LP_BLD_QUAD_TOP_RIGHT, LP_BLD_SWIZZLE_DONTCARE,102LP_BLD_QUAD_TOP_LEFT, LP_BLD_SWIZZLE_DONTCARE103};104105vec1 = lp_build_swizzle_aos(bld, a, swizzle1);106vec2 = lp_build_swizzle_aos(bld, a, swizzle2);107108if (bld->type.floating)109return LLVMBuildFSub(builder, vec2, vec1, "ddxddy");110else111return LLVMBuildSub(builder, vec2, vec1, "ddxddy");112}113114115/*116* Helper for building packed ddx/ddy vector for one coord (scalar per quad117* values). The vector will look like this (8-wide):118* ds1dx ds1dy dt1dx dt1dy ds2dx ds2dy dt2dx dt2dy119* This only needs 2 (v)shufps.120*/121LLVMValueRef122lp_build_packed_ddx_ddy_twocoord(struct lp_build_context *bld,123LLVMValueRef a, LLVMValueRef b)124{125struct gallivm_state *gallivm = bld->gallivm;126LLVMBuilderRef builder = gallivm->builder;127LLVMValueRef shuffles1[LP_MAX_VECTOR_LENGTH/4];128LLVMValueRef shuffles2[LP_MAX_VECTOR_LENGTH/4];129LLVMValueRef vec1, vec2;130unsigned length, num_quads, i;131132/* XXX: do hsub version */133length = bld->type.length;134num_quads = length / 4;135for (i = 0; i < num_quads; i++) {136unsigned s1 = 4 * i;137unsigned s2 = 4 * i + length;138shuffles1[4*i + 0] = lp_build_const_int32(gallivm, LP_BLD_QUAD_TOP_LEFT + s1);139shuffles1[4*i + 1] = lp_build_const_int32(gallivm, LP_BLD_QUAD_TOP_LEFT + s1);140shuffles1[4*i + 2] = lp_build_const_int32(gallivm, LP_BLD_QUAD_TOP_LEFT + s2);141shuffles1[4*i + 3] = lp_build_const_int32(gallivm, LP_BLD_QUAD_TOP_LEFT + s2);142shuffles2[4*i + 0] = lp_build_const_int32(gallivm, LP_BLD_QUAD_TOP_RIGHT + s1);143shuffles2[4*i + 1] = lp_build_const_int32(gallivm, LP_BLD_QUAD_BOTTOM_LEFT + s1);144shuffles2[4*i + 2] = lp_build_const_int32(gallivm, LP_BLD_QUAD_TOP_RIGHT + s2);145shuffles2[4*i + 3] = lp_build_const_int32(gallivm, LP_BLD_QUAD_BOTTOM_LEFT + s2);146}147vec1 = LLVMBuildShuffleVector(builder, a, b,148LLVMConstVector(shuffles1, length), "");149vec2 = LLVMBuildShuffleVector(builder, a, b,150LLVMConstVector(shuffles2, length), "");151if (bld->type.floating)152return LLVMBuildFSub(builder, vec2, vec1, "ddxddyddxddy");153else154return LLVMBuildSub(builder, vec2, vec1, "ddxddyddxddy");155}156157158/**159* Twiddle from quad format to row format160*161* src0 src1162* ######### ######### #################163* # 0 | 1 # # 4 | 5 # # 0 | 1 | 4 | 5 # src0164* #---+---# #---+---# -> #################165* # 2 | 3 # # 6 | 7 # # 2 | 3 | 6 | 7 # src1166* ######### ######### #################167*168*/169void170lp_bld_quad_twiddle(struct gallivm_state *gallivm,171struct lp_type lp_dst_type,172const LLVMValueRef* src,173unsigned src_count,174LLVMValueRef* dst)175{176LLVMBuilderRef builder = gallivm->builder;177LLVMTypeRef dst_type_ref;178LLVMTypeRef type2_ref;179struct lp_type type2;180unsigned i;181182assert((src_count % 2) == 0);183184/* Create a type with only 2 elements */185type2 = lp_dst_type;186type2.width = (lp_dst_type.width * lp_dst_type.length) / 2;187type2.length = 2;188type2.floating = 0;189190type2_ref = lp_build_vec_type(gallivm, type2);191dst_type_ref = lp_build_vec_type(gallivm, lp_dst_type);192193for (i = 0; i < src_count; i += 2) {194LLVMValueRef src0, src1;195196src0 = LLVMBuildBitCast(builder, src[i + 0], type2_ref, "");197src1 = LLVMBuildBitCast(builder, src[i + 1], type2_ref, "");198199dst[i + 0] = lp_build_interleave2(gallivm, type2, src0, src1, 0);200dst[i + 1] = lp_build_interleave2(gallivm, type2, src0, src1, 1);201202dst[i + 0] = LLVMBuildBitCast(builder, dst[i + 0], dst_type_ref, "");203dst[i + 1] = LLVMBuildBitCast(builder, dst[i + 1], dst_type_ref, "");204}205}206207208