gallivm: Fix format manipulation for big-endian
This patch fixes various format manipulation for big-endian architectures. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
This commit is contained in:
parent
b772d784b2
commit
e25abacc18
|
@ -49,6 +49,7 @@
|
||||||
#include "lp_bld_gather.h"
|
#include "lp_bld_gather.h"
|
||||||
#include "lp_bld_debug.h"
|
#include "lp_bld_debug.h"
|
||||||
#include "lp_bld_format.h"
|
#include "lp_bld_format.h"
|
||||||
|
#include "lp_bld_intr.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,6 +172,10 @@ lp_build_unpack_arith_rgba_aos(struct gallivm_state *gallivm,
|
||||||
* matches floating point size */
|
* matches floating point size */
|
||||||
assert (LLVMTypeOf(packed) == LLVMInt32TypeInContext(gallivm->context));
|
assert (LLVMTypeOf(packed) == LLVMInt32TypeInContext(gallivm->context));
|
||||||
|
|
||||||
|
#ifdef PIPE_ARCH_BIG_ENDIAN
|
||||||
|
packed = lp_build_bswap(gallivm, packed, lp_type_uint(32));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Broadcast the packed value to all four channels
|
/* Broadcast the packed value to all four channels
|
||||||
* before: packed = BGRA
|
* before: packed = BGRA
|
||||||
* after: packed = {BGRA, BGRA, BGRA, BGRA}
|
* after: packed = {BGRA, BGRA, BGRA, BGRA}
|
||||||
|
@ -396,6 +401,8 @@ lp_build_fetch_rgba_aos(struct gallivm_state *gallivm,
|
||||||
format_desc->block.bits <= type.width * 4 &&
|
format_desc->block.bits <= type.width * 4 &&
|
||||||
util_is_power_of_two(format_desc->block.bits)) {
|
util_is_power_of_two(format_desc->block.bits)) {
|
||||||
LLVMValueRef packed;
|
LLVMValueRef packed;
|
||||||
|
LLVMTypeRef dst_vec_type = lp_build_vec_type(gallivm, type);
|
||||||
|
unsigned vec_len = type.width * type.length;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The format matches the type (apart of a swizzle) so no need for
|
* The format matches the type (apart of a swizzle) so no need for
|
||||||
|
@ -406,11 +413,14 @@ lp_build_fetch_rgba_aos(struct gallivm_state *gallivm,
|
||||||
format_desc->block.bits, type.width*4,
|
format_desc->block.bits, type.width*4,
|
||||||
base_ptr, offset);
|
base_ptr, offset);
|
||||||
|
|
||||||
assert(format_desc->block.bits <= type.width * type.length);
|
assert(format_desc->block.bits <= vec_len);
|
||||||
|
|
||||||
packed = LLVMBuildBitCast(gallivm->builder, packed,
|
|
||||||
lp_build_vec_type(gallivm, type), "");
|
|
||||||
|
|
||||||
|
packed = LLVMBuildBitCast(gallivm->builder, packed, dst_vec_type, "");
|
||||||
|
#ifdef PIPE_ARCH_BIG_ENDIAN
|
||||||
|
if (type.floating)
|
||||||
|
packed = lp_build_bswap_vec(gallivm, packed, type,
|
||||||
|
lp_type_float_vec(type.width, vec_len));
|
||||||
|
#endif
|
||||||
return lp_build_format_swizzle_aos(format_desc, &bld, packed);
|
return lp_build_format_swizzle_aos(format_desc, &bld, packed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,67 @@
|
||||||
#include "lp_bld_type.h"
|
#include "lp_bld_type.h"
|
||||||
#include "lp_bld_conv.h"
|
#include "lp_bld_conv.h"
|
||||||
#include "lp_bld_pack.h"
|
#include "lp_bld_pack.h"
|
||||||
|
#include "lp_bld_intr.h"
|
||||||
|
#include "lp_bld_gather.h"
|
||||||
|
|
||||||
#include "util/u_memory.h"
|
#include "util/u_memory.h"
|
||||||
#include "util/u_format.h"
|
#include "util/u_format.h"
|
||||||
#include "pipe/p_state.h"
|
#include "pipe/p_state.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PIPE_ARCH_BIG_ENDIAN
|
||||||
|
static LLVMValueRef
|
||||||
|
lp_build_read_int_bswap(struct gallivm_state *gallivm,
|
||||||
|
LLVMValueRef base_ptr,
|
||||||
|
unsigned src_width,
|
||||||
|
LLVMTypeRef src_type,
|
||||||
|
unsigned i,
|
||||||
|
LLVMTypeRef dst_type)
|
||||||
|
{
|
||||||
|
LLVMBuilderRef builder = gallivm->builder;
|
||||||
|
LLVMValueRef index = lp_build_const_int32(gallivm, i);
|
||||||
|
LLVMValueRef ptr = LLVMBuildGEP(builder, base_ptr, &index, 1, "");
|
||||||
|
LLVMValueRef res = LLVMBuildLoad(builder, ptr, "");
|
||||||
|
res = lp_build_bswap(gallivm, res, lp_type_uint(src_width));
|
||||||
|
return LLVMBuildBitCast(builder, res, dst_type, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static LLVMValueRef
|
||||||
|
lp_build_fetch_read_big_endian(struct gallivm_state *gallivm,
|
||||||
|
struct lp_type src_type,
|
||||||
|
LLVMValueRef base_ptr)
|
||||||
|
{
|
||||||
|
LLVMBuilderRef builder = gallivm->builder;
|
||||||
|
unsigned src_width = src_type.width;
|
||||||
|
unsigned length = src_type.length;
|
||||||
|
LLVMTypeRef src_elem_type = LLVMIntTypeInContext(gallivm->context, src_width);
|
||||||
|
LLVMTypeRef dst_elem_type = lp_build_elem_type (gallivm, src_type);
|
||||||
|
LLVMTypeRef src_ptr_type = LLVMPointerType(src_elem_type, 0);
|
||||||
|
LLVMValueRef res;
|
||||||
|
|
||||||
|
base_ptr = LLVMBuildPointerCast(builder, base_ptr, src_ptr_type, "");
|
||||||
|
if (length == 1) {
|
||||||
|
/* Scalar */
|
||||||
|
res = lp_build_read_int_bswap(gallivm, base_ptr, src_width, src_elem_type,
|
||||||
|
0, dst_elem_type);
|
||||||
|
} else {
|
||||||
|
/* Vector */
|
||||||
|
LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length);
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
res = LLVMGetUndef(dst_vec_type);
|
||||||
|
for (i = 0; i < length; ++i) {
|
||||||
|
LLVMValueRef index = lp_build_const_int32(gallivm, i);
|
||||||
|
LLVMValueRef elem = lp_build_read_int_bswap(gallivm, base_ptr, src_width,
|
||||||
|
src_elem_type, i, dst_elem_type);
|
||||||
|
res = LLVMBuildInsertElement(builder, res, elem, index, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief lp_build_fetch_rgba_aos_array
|
* @brief lp_build_fetch_rgba_aos_array
|
||||||
*
|
*
|
||||||
|
@ -65,12 +121,14 @@ lp_build_fetch_rgba_aos_array(struct gallivm_state *gallivm,
|
||||||
src_vec_type = lp_build_vec_type(gallivm, src_type);
|
src_vec_type = lp_build_vec_type(gallivm, src_type);
|
||||||
|
|
||||||
/* Read whole vector from memory, unaligned */
|
/* Read whole vector from memory, unaligned */
|
||||||
if (!res) {
|
|
||||||
ptr = LLVMBuildGEP(builder, base_ptr, &offset, 1, "");
|
ptr = LLVMBuildGEP(builder, base_ptr, &offset, 1, "");
|
||||||
|
#ifdef PIPE_ARCH_BIG_ENDIAN
|
||||||
|
res = lp_build_fetch_read_big_endian(gallivm, src_type, ptr);
|
||||||
|
#else
|
||||||
ptr = LLVMBuildPointerCast(builder, ptr, LLVMPointerType(src_vec_type, 0), "");
|
ptr = LLVMBuildPointerCast(builder, ptr, LLVMPointerType(src_vec_type, 0), "");
|
||||||
res = LLVMBuildLoad(builder, ptr, "");
|
res = LLVMBuildLoad(builder, ptr, "");
|
||||||
lp_set_load_alignment(res, src_type.width / 8);
|
lp_set_load_alignment(res, src_type.width / 8);
|
||||||
}
|
#endif
|
||||||
|
|
||||||
/* Truncate doubles to float */
|
/* Truncate doubles to float */
|
||||||
if (src_type.floating && src_type.width == 64) {
|
if (src_type.floating && src_type.width == 64) {
|
||||||
|
|
|
@ -72,9 +72,15 @@ uyvy_to_yuv_soa(struct gallivm_state *gallivm,
|
||||||
assert(lp_check_value(type, i));
|
assert(lp_check_value(type, i));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* Little endian:
|
||||||
* y = (uyvy >> (16*i + 8)) & 0xff
|
* y = (uyvy >> (16*i + 8)) & 0xff
|
||||||
* u = (uyvy ) & 0xff
|
* u = (uyvy ) & 0xff
|
||||||
* v = (uyvy >> 16 ) & 0xff
|
* v = (uyvy >> 16 ) & 0xff
|
||||||
|
*
|
||||||
|
* Big endian:
|
||||||
|
* y = (uyvy >> (-16*i + 16)) & 0xff
|
||||||
|
* u = (uyvy >> 24) & 0xff
|
||||||
|
* v = (uyvy >> 8) & 0xff
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||||
|
@ -98,13 +104,23 @@ uyvy_to_yuv_soa(struct gallivm_state *gallivm,
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
LLVMValueRef shift;
|
LLVMValueRef shift;
|
||||||
|
#ifdef PIPE_ARCH_LITTLE_ENDIAN
|
||||||
shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(gallivm, type, 16), "");
|
shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(gallivm, type, 16), "");
|
||||||
shift = LLVMBuildAdd(builder, shift, lp_build_const_int_vec(gallivm, type, 8), "");
|
shift = LLVMBuildAdd(builder, shift, lp_build_const_int_vec(gallivm, type, 8), "");
|
||||||
|
#else
|
||||||
|
shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(gallivm, type, -16), "");
|
||||||
|
shift = LLVMBuildAdd(builder, shift, lp_build_const_int_vec(gallivm, type, 16), "");
|
||||||
|
#endif
|
||||||
*y = LLVMBuildLShr(builder, packed, shift, "");
|
*y = LLVMBuildLShr(builder, packed, shift, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PIPE_ARCH_LITTLE_ENDIAN
|
||||||
*u = packed;
|
*u = packed;
|
||||||
*v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 16), "");
|
*v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 16), "");
|
||||||
|
#else
|
||||||
|
*u = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 24), "");
|
||||||
|
*v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 8), "");
|
||||||
|
#endif
|
||||||
|
|
||||||
mask = lp_build_const_int_vec(gallivm, type, 0xff);
|
mask = lp_build_const_int_vec(gallivm, type, 0xff);
|
||||||
|
|
||||||
|
@ -140,9 +156,15 @@ yuyv_to_yuv_soa(struct gallivm_state *gallivm,
|
||||||
assert(lp_check_value(type, i));
|
assert(lp_check_value(type, i));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* Little endian:
|
||||||
* y = (yuyv >> 16*i) & 0xff
|
* y = (yuyv >> 16*i) & 0xff
|
||||||
* u = (yuyv >> 8 ) & 0xff
|
* u = (yuyv >> 8 ) & 0xff
|
||||||
* v = (yuyv >> 24 ) & 0xff
|
* v = (yuyv >> 24 ) & 0xff
|
||||||
|
*
|
||||||
|
* Big endian:
|
||||||
|
* y = (yuyv >> (-16*i + 24) & 0xff
|
||||||
|
* u = (yuyv >> 16) & 0xff
|
||||||
|
* v = (yuyv) & 0xff
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||||
|
@ -165,12 +187,22 @@ yuyv_to_yuv_soa(struct gallivm_state *gallivm,
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
LLVMValueRef shift;
|
LLVMValueRef shift;
|
||||||
|
#ifdef PIPE_ARCH_LITTLE_ENDIAN
|
||||||
shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(gallivm, type, 16), "");
|
shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(gallivm, type, 16), "");
|
||||||
|
#else
|
||||||
|
shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(gallivm, type, -16), "");
|
||||||
|
shift = LLVMBuildAdd(builder, shift, lp_build_const_int_vec(gallivm, type, 24), "");
|
||||||
|
#endif
|
||||||
*y = LLVMBuildLShr(builder, packed, shift, "");
|
*y = LLVMBuildLShr(builder, packed, shift, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PIPE_ARCH_LITTLE_ENDIAN
|
||||||
*u = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 8), "");
|
*u = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 8), "");
|
||||||
*v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 24), "");
|
*v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 24), "");
|
||||||
|
#else
|
||||||
|
*u = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 16), "");
|
||||||
|
*v = packed;
|
||||||
|
#endif
|
||||||
|
|
||||||
mask = lp_build_const_int_vec(gallivm, type, 0xff);
|
mask = lp_build_const_int_vec(gallivm, type, 0xff);
|
||||||
|
|
||||||
|
@ -302,10 +334,17 @@ rgb_to_rgba_aos(struct gallivm_state *gallivm,
|
||||||
* Make a 4 x unorm8 vector
|
* Make a 4 x unorm8 vector
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef PIPE_ARCH_LITTLE_ENDIAN
|
||||||
r = r;
|
r = r;
|
||||||
g = LLVMBuildShl(builder, g, lp_build_const_int_vec(gallivm, type, 8), "");
|
g = LLVMBuildShl(builder, g, lp_build_const_int_vec(gallivm, type, 8), "");
|
||||||
b = LLVMBuildShl(builder, b, lp_build_const_int_vec(gallivm, type, 16), "");
|
b = LLVMBuildShl(builder, b, lp_build_const_int_vec(gallivm, type, 16), "");
|
||||||
a = lp_build_const_int_vec(gallivm, type, 0xff000000);
|
a = lp_build_const_int_vec(gallivm, type, 0xff000000);
|
||||||
|
#else
|
||||||
|
r = LLVMBuildShl(builder, r, lp_build_const_int_vec(gallivm, type, 24), "");
|
||||||
|
g = LLVMBuildShl(builder, g, lp_build_const_int_vec(gallivm, type, 16), "");
|
||||||
|
b = LLVMBuildShl(builder, b, lp_build_const_int_vec(gallivm, type, 8), "");
|
||||||
|
a = lp_build_const_int_vec(gallivm, type, 0x000000ff);
|
||||||
|
#endif
|
||||||
|
|
||||||
rgba = r;
|
rgba = r;
|
||||||
rgba = LLVMBuildOr(builder, rgba, g, "");
|
rgba = LLVMBuildOr(builder, rgba, g, "");
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "lp_bld_format.h"
|
#include "lp_bld_format.h"
|
||||||
#include "lp_bld_gather.h"
|
#include "lp_bld_gather.h"
|
||||||
#include "lp_bld_init.h"
|
#include "lp_bld_init.h"
|
||||||
|
#include "lp_bld_intr.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,10 +93,15 @@ lp_build_gather_elem(struct gallivm_state *gallivm,
|
||||||
res = LLVMBuildLoad(gallivm->builder, ptr, "");
|
res = LLVMBuildLoad(gallivm->builder, ptr, "");
|
||||||
|
|
||||||
assert(src_width <= dst_width);
|
assert(src_width <= dst_width);
|
||||||
if (src_width > dst_width)
|
if (src_width > dst_width) {
|
||||||
res = LLVMBuildTrunc(gallivm->builder, res, dst_elem_type, "");
|
res = LLVMBuildTrunc(gallivm->builder, res, dst_elem_type, "");
|
||||||
if (src_width < dst_width)
|
} else if (src_width < dst_width) {
|
||||||
res = LLVMBuildZExt(gallivm->builder, res, dst_elem_type, "");
|
res = LLVMBuildZExt(gallivm->builder, res, dst_elem_type, "");
|
||||||
|
#ifdef PIPE_ARCH_BIG_ENDIAN
|
||||||
|
res = LLVMBuildShl(gallivm->builder, res,
|
||||||
|
LLVMConstInt(dst_elem_type, dst_width - src_width, 0), "");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -431,10 +431,16 @@ lp_build_swizzle_aos(struct lp_build_context *bld,
|
||||||
*
|
*
|
||||||
* For example, this will convert BGRA to RGBA by doing
|
* For example, this will convert BGRA to RGBA by doing
|
||||||
*
|
*
|
||||||
|
* Little endian:
|
||||||
* rgba = (bgra & 0x00ff0000) >> 16
|
* rgba = (bgra & 0x00ff0000) >> 16
|
||||||
* | (bgra & 0xff00ff00)
|
* | (bgra & 0xff00ff00)
|
||||||
* | (bgra & 0x000000ff) << 16
|
* | (bgra & 0x000000ff) << 16
|
||||||
*
|
*
|
||||||
|
* Big endian:A
|
||||||
|
* rgba = (bgra & 0x0000ff00) << 16
|
||||||
|
* | (bgra & 0x00ff00ff)
|
||||||
|
* | (bgra & 0xff000000) >> 16
|
||||||
|
*
|
||||||
* This is necessary not only for faster cause, but because X86 backend
|
* This is necessary not only for faster cause, but because X86 backend
|
||||||
* will refuse shuffles of <4 x i8> vectors
|
* will refuse shuffles of <4 x i8> vectors
|
||||||
*/
|
*/
|
||||||
|
@ -479,7 +485,11 @@ lp_build_swizzle_aos(struct lp_build_context *bld,
|
||||||
/* FIXME: big endian */
|
/* FIXME: big endian */
|
||||||
if (swizzles[chan] < 4 &&
|
if (swizzles[chan] < 4 &&
|
||||||
chan - swizzles[chan] == shift) {
|
chan - swizzles[chan] == shift) {
|
||||||
|
#ifdef PIPE_ARCH_LITTLE_ENDIAN
|
||||||
mask |= ((1ULL << type.width) - 1) << (swizzles[chan] * type.width);
|
mask |= ((1ULL << type.width) - 1) << (swizzles[chan] * type.width);
|
||||||
|
#else
|
||||||
|
mask |= ((1ULL << type.width) - 1) << (type4.width - type.width) >> (swizzles[chan] * type.width);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,11 +502,21 @@ lp_build_swizzle_aos(struct lp_build_context *bld,
|
||||||
masked = LLVMBuildAnd(builder, a,
|
masked = LLVMBuildAnd(builder, a,
|
||||||
lp_build_const_int_vec(bld->gallivm, type4, mask), "");
|
lp_build_const_int_vec(bld->gallivm, type4, mask), "");
|
||||||
if (shift > 0) {
|
if (shift > 0) {
|
||||||
|
#ifdef PIPE_ARCH_LITTLE_ENDIAN
|
||||||
shifted = LLVMBuildShl(builder, masked,
|
shifted = LLVMBuildShl(builder, masked,
|
||||||
lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), "");
|
lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), "");
|
||||||
|
#else
|
||||||
|
shifted = LLVMBuildLShr(builder, masked,
|
||||||
|
lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), "");
|
||||||
|
#endif
|
||||||
} else if (shift < 0) {
|
} else if (shift < 0) {
|
||||||
|
#ifdef PIPE_ARCH_LITTLE_ENDIAN
|
||||||
shifted = LLVMBuildLShr(builder, masked,
|
shifted = LLVMBuildLShr(builder, masked,
|
||||||
lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), "");
|
lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), "");
|
||||||
|
#else
|
||||||
|
shifted = LLVMBuildShl(builder, masked,
|
||||||
|
lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), "");
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
shifted = masked;
|
shifted = masked;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue