diff options
Diffstat (limited to 'src/gallium/auxiliary/gallivm')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld.h | 4 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_depth.c | 2 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_flow.c | 29 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_flow.h | 7 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_format.h | 11 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_format_soa.c | 160 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_init.c (renamed from src/gallium/auxiliary/gallivm/lp_bld_init.cpp) | 47 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_init.h | 16 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample.c | 15 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample.h | 11 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c | 63 |
11 files changed, 298 insertions, 67 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld.h b/src/gallium/auxiliary/gallivm/lp_bld.h index 70a4960f91..2fa682f400 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld.h +++ b/src/gallium/auxiliary/gallivm/lp_bld.h @@ -38,9 +38,9 @@ #include <llvm-c/Core.h> -/** Set version to 0 if missing to avoid #ifdef HAVE_LLVM everywhere */ +/** Ensure HAVE_LLVM is set to avoid #ifdef HAVE_LLVM everywhere */ #ifndef HAVE_LLVM -#define HAVE_LLVM 0x0207 +#error "HAVE_LLVM should be set with LLVM's version number, e.g. (0x0207 for 2.7)" #endif diff --git a/src/gallium/auxiliary/gallivm/lp_bld_depth.c b/src/gallium/auxiliary/gallivm/lp_bld_depth.c index c6d0e4bc04..564ea2e318 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_depth.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_depth.c @@ -116,7 +116,7 @@ lp_build_stencil_test_single(struct lp_build_context *bld, stencilVals = LLVMBuildAnd(bld->builder, stencilVals, valuemask, ""); } - res = lp_build_cmp(bld, stencil->func, stencilVals, stencilRef); + res = lp_build_cmp(bld, stencil->func, stencilRef, stencilVals); return res; } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_flow.c b/src/gallium/auxiliary/gallivm/lp_bld_flow.c index 106fc03e46..e60ab4f6ba 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_flow.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_flow.c @@ -570,6 +570,35 @@ lp_build_loop_end(LLVMBuilderRef builder, LLVMPositionBuilderAtEnd(builder, after_block); } +void +lp_build_loop_end_cond(LLVMBuilderRef builder, + LLVMValueRef end, + LLVMValueRef step, + int llvm_cond, + struct lp_build_loop_state *state) +{ + LLVMBasicBlockRef block = LLVMGetInsertBlock(builder); + LLVMValueRef function = LLVMGetBasicBlockParent(block); + LLVMValueRef next; + LLVMValueRef cond; + LLVMBasicBlockRef after_block; + + if (!step) + step = LLVMConstInt(LLVMTypeOf(end), 1, 0); + + next = LLVMBuildAdd(builder, state->counter, step, ""); + + cond = LLVMBuildICmp(builder, llvm_cond, next, end, ""); + + after_block = LLVMAppendBasicBlock(function, ""); + + LLVMBuildCondBr(builder, cond, after_block, state->block); + + LLVMAddIncoming(state->counter, &next, &block, 1); + + LLVMPositionBuilderAtEnd(builder, after_block); +} + /* diff --git a/src/gallium/auxiliary/gallivm/lp_bld_flow.h b/src/gallium/auxiliary/gallivm/lp_bld_flow.h index c2b50e1b60..745838570c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_flow.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_flow.h @@ -124,6 +124,13 @@ lp_build_loop_end(LLVMBuilderRef builder, LLVMValueRef step, struct lp_build_loop_state *state); +void +lp_build_loop_end_cond(LLVMBuilderRef builder, + LLVMValueRef end, + LLVMValueRef step, + int cond, /* LLVM condition */ + struct lp_build_loop_state *state); + diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format.h b/src/gallium/auxiliary/gallivm/lp_bld_format.h index 73ab6de3f2..bb1298ed3f 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_format.h @@ -80,4 +80,15 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder, LLVMValueRef *rgba); +void +lp_build_fetch_rgba_soa(LLVMBuilderRef builder, + const struct util_format_description *format_desc, + struct lp_type type, + LLVMValueRef base_ptr, + LLVMValueRef offsets, + LLVMValueRef i, + LLVMValueRef j, + LLVMValueRef *rgba); + + #endif /* !LP_BLD_FORMAT_H */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c index 9f242844e5..2b66162eb4 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c @@ -27,10 +27,14 @@ #include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_string.h" #include "lp_bld_type.h" #include "lp_bld_const.h" #include "lp_bld_conv.h" +#include "lp_bld_sample.h" /* for lp_build_gather */ +#include "lp_bld_init.h" #include "lp_bld_format.h" @@ -109,7 +113,7 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder, unsigned start; unsigned chan; - /* FIXME: Support more pixel formats */ + assert(format_desc->layout == UTIL_FORMAT_LAYOUT_PLAIN); assert(format_desc->block.width == 1); assert(format_desc->block.height == 1); assert(format_desc->block.bits <= type.width); @@ -223,8 +227,17 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder, break; case UTIL_FORMAT_TYPE_FIXED: - assert(0); - input = lp_build_undef(type); + if (type.floating) { + double scale = 1.0 / ((1 << (format_desc->channel[chan].size/2)) - 1); + LLVMValueRef scale_val = lp_build_const_vec(type, scale); + input = LLVMBuildSIToFP(builder, input, lp_build_vec_type(type), ""); + input = LLVMBuildMul(builder, input, scale_val, ""); + } + else { + /* FIXME */ + assert(0); + input = lp_build_undef(type); + } break; default: @@ -240,3 +253,144 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder, lp_build_format_swizzle_soa(format_desc, type, inputs, rgba); } + + +/** + * Fetch a pixel into a SoA. + * + * i and j are the sub-block pixel coordinates. + */ +void +lp_build_fetch_rgba_soa(LLVMBuilderRef builder, + const struct util_format_description *format_desc, + struct lp_type type, + LLVMValueRef base_ptr, + LLVMValueRef offset, + LLVMValueRef i, + LLVMValueRef j, + LLVMValueRef *rgba) +{ + + if (format_desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && + (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || + format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) && + format_desc->block.width == 1 && + format_desc->block.height == 1 && + format_desc->block.bits <= type.width && + (format_desc->channel[0].type != UTIL_FORMAT_TYPE_FLOAT || + format_desc->channel[0].size == 32)) + { + /* + * The packed pixel fits into an element of the destination format. Put + * the packed pixels into a vector and estract each component for all + * vector elements in parallel. + */ + + LLVMValueRef packed; + + /* + * gather the texels from the texture + */ + packed = lp_build_gather(builder, + type.length, + format_desc->block.bits, + type.width, + base_ptr, offset); + + /* + * convert texels to float rgba + */ + lp_build_unpack_rgba_soa(builder, + format_desc, + type, + packed, rgba); + } + else { + /* + * Fallback to calling util_format_description::fetch_rgba_float for each + * pixel. + * + * This is definitely not the most efficient way of fetching pixels, as + * we miss the opportunity to do vectorization, but this it is a + * convenient for formats or scenarios for which there was no opportunity + * or incentive to optimize. + */ + + LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder))); + char name[256]; + LLVMValueRef function; + LLVMValueRef tmp; + unsigned k, chan; + + assert(type.floating); + + util_snprintf(name, sizeof name, "util_format_%s_fetch_rgba_float", format_desc->short_name); + + /* + * Declare and bind format_desc->fetch_rgba_float(). + */ + + function = LLVMGetNamedFunction(module, name); + if (!function) { + LLVMTypeRef ret_type; + LLVMTypeRef arg_types[4]; + LLVMTypeRef function_type; + + ret_type = LLVMVoidType(); + arg_types[0] = LLVMPointerType(LLVMFloatType(), 0); + arg_types[1] = LLVMPointerType(LLVMInt8Type(), 0); + arg_types[3] = arg_types[2] = LLVMIntType(sizeof(unsigned) * 8); + function_type = LLVMFunctionType(ret_type, arg_types, Elements(arg_types), 0); + function = LLVMAddFunction(module, name, function_type); + + LLVMSetFunctionCallConv(function, LLVMCCallConv); + LLVMSetLinkage(function, LLVMExternalLinkage); + + assert(LLVMIsDeclaration(function)); + + LLVMAddGlobalMapping(lp_build_engine, function, format_desc->fetch_rgba_float); + } + + for (chan = 0; chan < 4; ++chan) { + rgba[chan] = lp_build_undef(type); + } + + tmp = LLVMBuildArrayAlloca(builder, + LLVMFloatType(), + LLVMConstInt(LLVMInt32Type(), 4, 0), + ""); + + /* + * Invoke format_desc->fetch_rgba_float() for each pixel and insert the result + * in the SoA vectors. + */ + + for(k = 0; k < type.length; ++k) { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), k, 0); + LLVMValueRef offset_elem; + LLVMValueRef ptr; + LLVMValueRef i_elem, j_elem; + LLVMValueRef args[4]; + + offset_elem = LLVMBuildExtractElement(builder, offset, index, ""); + ptr = LLVMBuildGEP(builder, base_ptr, &offset_elem, 1, ""); + + i_elem = LLVMBuildExtractElement(builder, i, index, ""); + j_elem = LLVMBuildExtractElement(builder, j, index, ""); + + args[0] = tmp; + args[1] = ptr; + args[2] = i_elem; + args[3] = j_elem; + + LLVMBuildCall(builder, function, args, 4, ""); + + for (chan = 0; chan < 4; ++chan) { + LLVMValueRef chan_val = LLVMConstInt(LLVMInt32Type(), chan, 0), + tmp_chan = LLVMBuildGEP(builder, tmp, &chan_val, 1, ""); + tmp_chan = LLVMBuildLoad(builder, tmp_chan, ""); + rgba[chan] = LLVMBuildInsertElement(builder, rgba[chan], tmp_chan, index, ""); + } + } + } +} diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.cpp b/src/gallium/auxiliary/gallivm/lp_bld_init.c index 067397a520..de07c222a3 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_init.cpp +++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c @@ -26,33 +26,42 @@ **************************************************************************/ -#include <llvm/Config/config.h> -#include <llvm/Target/TargetSelect.h> -#include <llvm/Target/TargetOptions.h> - -#include "pipe/p_config.h" - +#include "pipe/p_compiler.h" +#include "util/u_debug.h" #include "lp_bld_init.h" -extern "C" void LLVMLinkInJIT(); +LLVMModuleRef lp_build_module = NULL; +LLVMExecutionEngineRef lp_build_engine = NULL; +LLVMModuleProviderRef lp_build_provider = NULL; +LLVMTargetDataRef lp_build_target = NULL; -extern "C" void +void lp_build_init(void) { -#if defined(PIPE_OS_WINDOWS) && defined(PIPE_ARCH_X86) - /* - * This is mis-detected on some hardware / software combinations. - */ - llvm::StackAlignment = 4; - llvm::RealignStack = true; -#endif - - /* Same as LLVMInitializeNativeTarget(); */ - llvm::InitializeNativeTarget(); + LLVMInitializeNativeTarget(); LLVMLinkInJIT(); + + if (!lp_build_module) + lp_build_module = LLVMModuleCreateWithName("gallivm"); + + if (!lp_build_provider) + lp_build_provider = LLVMCreateModuleProviderForExistingModule(lp_build_module); + + if (!lp_build_engine) { + char *error = NULL; + + if (LLVMCreateJITCompiler(&lp_build_engine, lp_build_provider, 1, &error)) { + _debug_printf("%s\n", error); + LLVMDisposeMessage(error); + assert(0); + } + } + + if (!lp_build_target) + lp_build_target = LLVMGetExecutionEngineTargetData(lp_build_engine); } @@ -64,6 +73,6 @@ lp_build_init(void) */ #if defined(_MSC_VER) && defined(_DEBUG) #include <crtdefs.h> -extern "C" _CRTIMP void __cdecl +_CRTIMP void __cdecl _invalid_parameter_noinfo(void) {} #endif diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.h b/src/gallium/auxiliary/gallivm/lp_bld_init.h index 07f50d1c43..0ec2afcd1b 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_init.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_init.h @@ -30,18 +30,18 @@ #define LP_BLD_INIT_H -#ifdef __cplusplus -extern "C" { -#endif +#include "lp_bld.h" +#include <llvm-c/ExecutionEngine.h> -void -lp_build_init(void); +extern LLVMModuleRef lp_build_module; +extern LLVMExecutionEngineRef lp_build_engine; +extern LLVMModuleProviderRef lp_build_provider; +extern LLVMTargetDataRef lp_build_target; -#ifdef __cplusplus -} -#endif +void +lp_build_init(void); #endif /* !LP_BLD_INIT_H */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c index bb76ad4c6b..eb75b9b393 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c @@ -51,9 +51,11 @@ */ void lp_sampler_static_state(struct lp_sampler_static_state *state, - const struct pipe_texture *texture, + const struct pipe_sampler_view *view, const struct pipe_sampler_state *sampler) { + const struct pipe_resource *texture = view->texture; + memset(state, 0, sizeof *state); if(!texture) @@ -74,7 +76,7 @@ lp_sampler_static_state(struct lp_sampler_static_state *state, * regarding 1D/2D/3D/CUBE textures, wrap modes, etc. */ - state->format = texture->format; + state->format = view->format; state->target = texture->target; state->pot_width = util_is_pot(texture->width0); state->pot_height = util_is_pot(texture->height0); @@ -104,6 +106,10 @@ lp_sampler_static_state(struct lp_sampler_static_state *state, state->border_color[1] = sampler->border_color[1]; state->border_color[2] = sampler->border_color[2]; state->border_color[3] = sampler->border_color[3]; + + /* + * FIXME: Handle the remainder of pipe_sampler_view. + */ } @@ -157,9 +163,10 @@ lp_build_gather(LLVMBuilderRef builder, /** - * Compute the offset of a pixel. + * Compute the offset of a pixel block. * - * x, y, z, y_stride, z_stride are vectors + * x, y, z, y_stride, z_stride are vectors, and they refer to pixel blocks, as + * per format description, and not individual pixels. */ LLVMValueRef lp_build_sample_offset(struct lp_build_context *bld, diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h index 92f3c57435..8c1af95c50 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h @@ -38,7 +38,8 @@ #include "gallivm/lp_bld.h" -struct pipe_texture; +struct pipe_resource; +struct pipe_sampler_view; struct pipe_sampler_state; struct util_format_description; struct lp_type; @@ -48,14 +49,14 @@ struct lp_build_context; /** * Sampler static state. * - * These are the bits of state from pipe_texture and pipe_sampler_state that + * These are the bits of state from pipe_resource and pipe_sampler_state that * are embedded in the generated code. */ struct lp_sampler_static_state { /* pipe_texture's state */ enum pipe_format format; - unsigned target:2; + unsigned target:3; unsigned pot_width:1; unsigned pot_height:1; unsigned pot_depth:1; @@ -78,7 +79,7 @@ struct lp_sampler_static_state /** * Sampler dynamic state. * - * These are the bits of state from pipe_texture and pipe_sampler_state that + * These are the bits of state from pipe_resource and pipe_sampler_state that * are computed in runtime. * * There are obtained through callbacks, as we don't want to tie the texture @@ -130,7 +131,7 @@ struct lp_sampler_dynamic_state */ void lp_sampler_static_state(struct lp_sampler_static_state *state, - const struct pipe_texture *texture, + const struct pipe_sampler_view *view, const struct pipe_sampler_state *sampler); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c index 5b56f2cf3b..395eaaba26 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -211,7 +211,7 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld, const int dims = texture_dims(bld->static_state->target); struct lp_build_context *int_coord_bld = &bld->int_coord_bld; LLVMValueRef offset; - LLVMValueRef packed; + LLVMValueRef i, j; LLVMValueRef use_border = NULL; /* use_border = x < 0 || x >= width || y < 0 || y >= height */ @@ -249,6 +249,43 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld, } /* + * Describe the coordinates in terms of pixel blocks. + * + * TODO: pixel blocks are power of two. LLVM should convert rem/div to + * bit arithmetic. Verify this. + */ + + if (bld->format_desc->block.width == 1) { + i = bld->uint_coord_bld.zero; + } + else { + LLVMValueRef block_width = lp_build_const_int_vec(bld->uint_coord_bld.type, bld->format_desc->block.width); + i = LLVMBuildURem(bld->builder, x, block_width, ""); + x = LLVMBuildUDiv(bld->builder, x, block_width, ""); + } + + if (bld->format_desc->block.height == 1) { + j = bld->uint_coord_bld.zero; + } + else { + LLVMValueRef block_height = lp_build_const_int_vec(bld->uint_coord_bld.type, bld->format_desc->block.height); + j = LLVMBuildURem(bld->builder, y, block_height, ""); + y = LLVMBuildUDiv(bld->builder, y, block_height, ""); + } + + /* convert x,y,z coords to linear offset from start of texture, in bytes */ + offset = lp_build_sample_offset(&bld->uint_coord_bld, + bld->format_desc, + x, y, z, y_stride, z_stride); + + lp_build_fetch_rgba_soa(bld->builder, + bld->format_desc, + bld->texel_type, + data_ptr, offset, + i, j, + texel); + + /* * Note: if we find an app which frequently samples the texture border * we might want to implement a true conditional here to avoid sampling * the texture whenever possible (since that's quite a bit of code). @@ -263,30 +300,6 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld, * the texel color results with the border color. */ - /* convert x,y,z coords to linear offset from start of texture, in bytes */ - offset = lp_build_sample_offset(&bld->uint_coord_bld, - bld->format_desc, - x, y, z, y_stride, z_stride); - - assert(bld->format_desc->block.width == 1); - assert(bld->format_desc->block.height == 1); - assert(bld->format_desc->block.bits <= bld->texel_type.width); - - /* gather the texels from the texture */ - packed = lp_build_gather(bld->builder, - bld->texel_type.length, - bld->format_desc->block.bits, - bld->texel_type.width, - data_ptr, offset); - - texel[0] = texel[1] = texel[2] = texel[3] = NULL; - - /* convert texels to float rgba */ - lp_build_unpack_rgba_soa(bld->builder, - bld->format_desc, - bld->texel_type, - packed, texel); - if (use_border) { /* select texel color or border color depending on use_border */ int chan; |