From 8ebfcf31eb905b7d47e520c04420620ae21bdf4e Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 25 Jun 2010 19:31:09 -0400 Subject: draw: limit the number of vertex shader variants kept around we used to create and cache unltimited number of variant, this change limits the number of variants kept around to a fixed number. the change is based on a similar patch by Roland for llvmpipe fragment shaders. --- src/gallium/auxiliary/SConscript | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/gallium/auxiliary/SConscript') diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index 6242ab0c59..1f400575a7 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -218,7 +218,8 @@ if env['llvm']: 'gallivm/lp_bld_type.c', 'draw/draw_llvm.c', 'draw/draw_pt_fetch_shade_pipeline_llvm.c', - 'draw/draw_llvm_translate.c' + 'draw/draw_llvm_translate.c', + 'draw/draw_vs_llvm.c' ] gallium = env.ConvenienceLibrary( -- cgit v1.2.3 From 3cc4301c146e2a6e680939456ea3df4ec2d12e3e Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 2 Jul 2010 11:40:22 +0100 Subject: gallivm: Code generate YUV format unpacking. --- src/gallium/auxiliary/Makefile | 1 + src/gallium/auxiliary/SConscript | 1 + src/gallium/auxiliary/gallivm/lp_bld_format.h | 12 + src/gallium/auxiliary/gallivm/lp_bld_format_aos.c | 22 ++ src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c | 395 ++++++++++++++++++++++ 5 files changed, 431 insertions(+) create mode 100644 src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c (limited to 'src/gallium/auxiliary/SConscript') diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index 103d1d6588..36a46aee3b 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -154,6 +154,7 @@ GALLIVM_SOURCES = \ gallivm/lp_bld_flow.c \ gallivm/lp_bld_format_aos.c \ gallivm/lp_bld_format_soa.c \ + gallivm/lp_bld_format_yuv.c \ gallivm/lp_bld_init.c \ gallivm/lp_bld_intr.c \ gallivm/lp_bld_logic.c \ diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index 1f400575a7..0b19444ad3 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -203,6 +203,7 @@ if env['llvm']: 'gallivm/lp_bld_flow.c', 'gallivm/lp_bld_format_aos.c', 'gallivm/lp_bld_format_soa.c', + 'gallivm/lp_bld_format_yuv.c', 'gallivm/lp_bld_intr.c', 'gallivm/lp_bld_logic.c', 'gallivm/lp_bld_init.c', diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format.h b/src/gallium/auxiliary/gallivm/lp_bld_format.h index c335ca46a7..a853d7ca41 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_format.h @@ -94,5 +94,17 @@ lp_build_fetch_rgba_soa(LLVMBuilderRef builder, LLVMValueRef j, LLVMValueRef rgba_out[4]); +/* + * YUV + */ + + +LLVMValueRef +lp_build_unpack_subsampled_to_rgba_aos(LLVMBuilderRef builder, + const struct util_format_description *format_desc, + unsigned n, + LLVMValueRef packed, + LLVMValueRef i, + LLVMValueRef j); #endif /* !LP_BLD_FORMAT_H */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c index bec2a80d76..cc72a31d72 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c @@ -366,6 +366,8 @@ lp_build_pack_rgba_aos(LLVMBuilderRef builder, } + + /** * Fetch a pixel into a 4 float AoS. * @@ -429,6 +431,26 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder, return lp_build_unpack_rgba_aos(format_desc, &bld, packed); } } + else if (format_desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) { + LLVMValueRef packed; + LLVMValueRef rgba; + + ptr = LLVMBuildBitCast(builder, ptr, + LLVMPointerType(LLVMInt32Type(), 0), + "packed_ptr"); + + packed = LLVMBuildLoad(builder, ptr, "packed"); + + rgba = lp_build_unpack_subsampled_to_rgba_aos(builder, format_desc, + 1, packed, i, j); + + lp_build_conv(builder, + lp_unorm8_vec4_type(), + type, + &rgba, 1, &rgba, 1); + + return rgba; + } else if (format_desc->fetch_rgba_float) { /* * Fallback to calling util_format_description::fetch_rgba_float. diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c b/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c new file mode 100644 index 0000000000..5fe2ab6e3b --- /dev/null +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c @@ -0,0 +1,395 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + + +/** + * @file + * YUV pixel format manipulation. + * + * @author Jose Fonseca + */ + + +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_string.h" + +#include "lp_bld_arit.h" +#include "lp_bld_init.h" +#include "lp_bld_type.h" +#include "lp_bld_const.h" +#include "lp_bld_conv.h" +#include "lp_bld_format.h" + + +/** + * Extract Y, U, V channels from packed UYVY. + * @param packed is a vector with the packed UYVY blocks + * @param i is a vector with the x pixel coordinate (0 or 1) + */ +static void +uyvy_to_yuv_soa(LLVMBuilderRef builder, + unsigned n, + LLVMValueRef packed, + LLVMValueRef i, + LLVMValueRef *y, + LLVMValueRef *u, + LLVMValueRef *v) +{ + struct lp_type type; + LLVMValueRef shift, mask; + + memset(&type, 0, sizeof type); + type.width = 32; + type.length = n; + + assert(lp_check_value(type, packed)); + assert(lp_check_value(type, i)); + + /* + * y = (uyvy >> 16*i) & 0xff + * u = (uyvy ) & 0xff + * v = (uyvy >> 16 ) & 0xff + */ + + shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(type, 16), ""); + shift = LLVMBuildAdd(builder, shift, lp_build_const_int_vec(type, 8), ""); + *y = LLVMBuildLShr(builder, packed, shift, ""); + *u = packed; + *v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 16), ""); + + mask = lp_build_const_int_vec(type, 0xff); + + *y = LLVMBuildAnd(builder, *y, mask, "y"); + *u = LLVMBuildAnd(builder, *u, mask, "u"); + *v = LLVMBuildAnd(builder, *v, mask, "v"); +} + + +/** + * Extract Y, U, V channels from packed YUYV. + * @param packed is a vector with the packed YUYV blocks + * @param i is a vector with the x pixel coordinate (0 or 1) + */ +static void +yuyv_to_yuv_soa(LLVMBuilderRef builder, + unsigned n, + LLVMValueRef packed, + LLVMValueRef i, + LLVMValueRef *y, + LLVMValueRef *u, + LLVMValueRef *v) +{ + struct lp_type type; + LLVMValueRef shift, mask; + + memset(&type, 0, sizeof type); + type.width = 32; + type.length = n; + + assert(lp_check_value(type, packed)); + assert(lp_check_value(type, i)); + + /* + * y = (yuyv >> 16*i) & 0xff + * u = (yuyv >> 8 ) & 0xff + * v = (yuyv >> 24 ) & 0xff + */ + + shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(type, 16), ""); + *y = LLVMBuildLShr(builder, packed, shift, ""); + *u = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 8), ""); + *v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 24), ""); + + mask = lp_build_const_int_vec(type, 0xff); + + *y = LLVMBuildAnd(builder, *y, mask, "y"); + *u = LLVMBuildAnd(builder, *u, mask, "u"); + *v = LLVMBuildAnd(builder, *v, mask, "v"); +} + + +static INLINE void +yuv_to_rgb_soa(LLVMBuilderRef builder, + unsigned n, + LLVMValueRef y, LLVMValueRef u, LLVMValueRef v, + LLVMValueRef *r, LLVMValueRef *g, LLVMValueRef *b) +{ + struct lp_type type; + struct lp_build_context bld; + + LLVMValueRef c0; + LLVMValueRef c8; + LLVMValueRef c16; + LLVMValueRef c128; + LLVMValueRef c255; + + LLVMValueRef cy; + LLVMValueRef cug; + LLVMValueRef cub; + LLVMValueRef cvr; + LLVMValueRef cvg; + + memset(&type, 0, sizeof type); + type.sign = TRUE; + type.width = 32; + type.length = n; + + lp_build_context_init(&bld, builder, type); + + assert(lp_check_value(type, y)); + assert(lp_check_value(type, u)); + assert(lp_check_value(type, v)); + + /* + * Constants + */ + + c0 = lp_build_const_int_vec(type, 0); + c8 = lp_build_const_int_vec(type, 8); + c16 = lp_build_const_int_vec(type, 16); + c128 = lp_build_const_int_vec(type, 128); + c255 = lp_build_const_int_vec(type, 255); + + cy = lp_build_const_int_vec(type, 298); + cug = lp_build_const_int_vec(type, -100); + cub = lp_build_const_int_vec(type, 516); + cvr = lp_build_const_int_vec(type, 409); + cvg = lp_build_const_int_vec(type, -208); + + /* + * y -= 16; + * u -= 128; + * v -= 128; + */ + + y = LLVMBuildSub(builder, y, c16, ""); + u = LLVMBuildSub(builder, u, c128, ""); + v = LLVMBuildSub(builder, v, c128, ""); + + /* + * r = 298 * _y + 409 * _v + 128; + * g = 298 * _y - 100 * _u - 208 * _v + 128; + * b = 298 * _y + 516 * _u + 128; + */ + + y = LLVMBuildMul(builder, y, cy, ""); + y = LLVMBuildAdd(builder, y, c128, ""); + + *r = LLVMBuildMul(builder, v, cvr, ""); + *g = LLVMBuildAdd(builder, + LLVMBuildMul(builder, u, cug, ""), + LLVMBuildMul(builder, v, cvg, ""), + ""); + *b = LLVMBuildMul(builder, u, cub, ""); + + *r = LLVMBuildAdd(builder, *r, y, ""); + *g = LLVMBuildAdd(builder, *g, y, ""); + *b = LLVMBuildAdd(builder, *b, y, ""); + + /* + * r >>= 8; + * g >>= 8; + * b >>= 8; + */ + + *r = LLVMBuildAShr(builder, *r, c8, "r"); + *g = LLVMBuildAShr(builder, *g, c8, "g"); + *b = LLVMBuildAShr(builder, *b, c8, "b"); + + /* + * Clamp + */ + + *r = lp_build_clamp(&bld, *r, c0, c255); + *g = lp_build_clamp(&bld, *g, c0, c255); + *b = lp_build_clamp(&bld, *b, c0, c255); +} + + +static LLVMValueRef +rgb_to_rgba_aos(LLVMBuilderRef builder, + unsigned n, + LLVMValueRef r, LLVMValueRef g, LLVMValueRef b) +{ + struct lp_type type; + LLVMValueRef a; + LLVMValueRef rgba; + + memset(&type, 0, sizeof type); + type.sign = TRUE; + type.width = 32; + type.length = n; + + assert(lp_check_value(type, r)); + assert(lp_check_value(type, g)); + assert(lp_check_value(type, b)); + + /* + * Make a 4 x unorm8 vector + */ + + r = r; + g = LLVMBuildShl(builder, g, lp_build_const_int_vec(type, 8), ""); + b = LLVMBuildShl(builder, b, lp_build_const_int_vec(type, 16), ""); + a = lp_build_const_int_vec(type, 0xff000000); + + rgba = r; + rgba = LLVMBuildOr(builder, rgba, g, ""); + rgba = LLVMBuildOr(builder, rgba, b, ""); + rgba = LLVMBuildOr(builder, rgba, a, ""); + + rgba = LLVMBuildBitCast(builder, rgba, + LLVMVectorType(LLVMInt8Type(), 4*n), ""); + + return rgba; +} + + +/** + * Convert from packed UYVY to <4n x i8> RGBA AoS + */ +static LLVMValueRef +uyvy_to_rgba_aos(LLVMBuilderRef builder, + unsigned n, + LLVMValueRef packed, + LLVMValueRef i) +{ + LLVMValueRef y, u, v; + LLVMValueRef r, g, b; + LLVMValueRef rgba; + + uyvy_to_yuv_soa(builder, n, packed, i, &y, &u, &v); + yuv_to_rgb_soa(builder, n, y, u, v, &r, &g, &b); + rgba = rgb_to_rgba_aos(builder, n, r, g, b); + + return rgba; +} + + +/** + * Convert from packed YUYV to <4n x i8> RGBA AoS + */ +static LLVMValueRef +yuyv_to_rgba_aos(LLVMBuilderRef builder, + unsigned n, + LLVMValueRef packed, + LLVMValueRef i) +{ + LLVMValueRef y, u, v; + LLVMValueRef r, g, b; + LLVMValueRef rgba; + + yuyv_to_yuv_soa(builder, n, packed, i, &y, &u, &v); + yuv_to_rgb_soa(builder, n, y, u, v, &r, &g, &b); + rgba = rgb_to_rgba_aos(builder, n, r, g, b); + + return rgba; +} + + +/** + * Convert from packed RG_BG to <4n x i8> RGBA AoS + */ +static LLVMValueRef +rgbg_to_rgba_aos(LLVMBuilderRef builder, + unsigned n, + LLVMValueRef packed, + LLVMValueRef i) +{ + LLVMValueRef r, g, b; + LLVMValueRef rgba; + + uyvy_to_yuv_soa(builder, n, packed, i, &g, &r, &b); + rgba = rgb_to_rgba_aos(builder, n, r, g, b); + + return rgba; +} + + +/** + * Convert from packed GR_GB to <4n x i8> RGBA AoS + */ +static LLVMValueRef +grgb_to_rgba_aos(LLVMBuilderRef builder, + unsigned n, + LLVMValueRef packed, + LLVMValueRef i) +{ + LLVMValueRef r, g, b; + LLVMValueRef rgba; + + yuyv_to_yuv_soa(builder, n, packed, i, &g, &r, &b); + rgba = rgb_to_rgba_aos(builder, n, r, g, b); + + return rgba; +} + + +/** + * @param n is the number of pixels processed + * @param packed is a vector with the packed YUYV blocks + * @param i is a vector with the x pixel coordinate (0 or 1) + * @return a <4*n x i8> vector with the pixel RGBA values in AoS + */ +LLVMValueRef +lp_build_unpack_subsampled_to_rgba_aos(LLVMBuilderRef builder, + const struct util_format_description *format_desc, + unsigned n, + LLVMValueRef packed, + LLVMValueRef i, + LLVMValueRef j) +{ + LLVMValueRef rgba; + + assert(format_desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED); + + (void)j; + + switch (format_desc->format) { + case PIPE_FORMAT_UYVY: + rgba = uyvy_to_rgba_aos(builder, n, packed, i); + break; + case PIPE_FORMAT_YUYV: + rgba = yuyv_to_rgba_aos(builder, n, packed, i); + break; + case PIPE_FORMAT_R8G8_B8G8_UNORM: + rgba = rgbg_to_rgba_aos(builder, n, packed, i); + break; + case PIPE_FORMAT_G8R8_G8B8_UNORM: + rgba = grgb_to_rgba_aos(builder, n, packed, i); + break; + default: + assert(0); + rgba = LLVMGetUndef(LLVMVectorType(LLVMInt8Type(), 4*n)); + break; + } + + return rgba; +} + -- cgit v1.2.3 From bb1546f55be3b243b71d39e5fb7457c5b21e32c9 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 2 Jul 2010 16:57:57 +0100 Subject: gallivm: Move gather functions to its own module. They need to grow, and they provide basic functionality which is not specific to sampling. --- src/gallium/auxiliary/Makefile | 1 + src/gallium/auxiliary/SConscript | 1 + src/gallium/auxiliary/gallivm/lp_bld_format_aos.c | 1 + src/gallium/auxiliary/gallivm/lp_bld_format_soa.c | 2 +- src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c | 1 + src/gallium/auxiliary/gallivm/lp_bld_gather.c | 148 ++++++++++++++++++++++ src/gallium/auxiliary/gallivm/lp_bld_gather.h | 61 +++++++++ src/gallium/auxiliary/gallivm/lp_bld_sample.c | 51 -------- src/gallium/auxiliary/gallivm/lp_bld_sample.h | 9 -- src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c | 1 + 10 files changed, 215 insertions(+), 61 deletions(-) create mode 100644 src/gallium/auxiliary/gallivm/lp_bld_gather.c create mode 100644 src/gallium/auxiliary/gallivm/lp_bld_gather.h (limited to 'src/gallium/auxiliary/SConscript') diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index 36a46aee3b..91f8b1034a 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -155,6 +155,7 @@ GALLIVM_SOURCES = \ gallivm/lp_bld_format_aos.c \ gallivm/lp_bld_format_soa.c \ gallivm/lp_bld_format_yuv.c \ + gallivm/lp_bld_gather.c \ gallivm/lp_bld_init.c \ gallivm/lp_bld_intr.c \ gallivm/lp_bld_logic.c \ diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index 0b19444ad3..af3f47bbf0 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -204,6 +204,7 @@ if env['llvm']: 'gallivm/lp_bld_format_aos.c', 'gallivm/lp_bld_format_soa.c', 'gallivm/lp_bld_format_yuv.c', + 'gallivm/lp_bld_gather.c', 'gallivm/lp_bld_intr.c', 'gallivm/lp_bld_logic.c', 'gallivm/lp_bld_init.c', diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c index cc72a31d72..c3d1fc7c3d 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c @@ -45,6 +45,7 @@ #include "lp_bld_const.h" #include "lp_bld_conv.h" #include "lp_bld_swizzle.h" +#include "lp_bld_gather.h" #include "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 a4a36a090d..687bce4348 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c @@ -36,7 +36,7 @@ #include "lp_bld_const.h" #include "lp_bld_conv.h" #include "lp_bld_swizzle.h" -#include "lp_bld_sample.h" /* for lp_build_gather */ +#include "lp_bld_gather.h" #include "lp_bld_format.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c b/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c index 5fe2ab6e3b..d3eba50b77 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c @@ -44,6 +44,7 @@ #include "lp_bld_type.h" #include "lp_bld_const.h" #include "lp_bld_conv.h" +#include "lp_bld_gather.h" #include "lp_bld_format.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_gather.c b/src/gallium/auxiliary/gallivm/lp_bld_gather.c new file mode 100644 index 0000000000..d60472e065 --- /dev/null +++ b/src/gallium/auxiliary/gallivm/lp_bld_gather.c @@ -0,0 +1,148 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + + +#include "util/u_debug.h" +#include "lp_bld_debug.h" +#include "lp_bld_const.h" +#include "lp_bld_format.h" +#include "lp_bld_gather.h" + + +/** + * Get the pointer to one element from scatter positions in memory. + * + * @sa lp_build_gather() + */ +LLVMValueRef +lp_build_gather_elem_ptr(LLVMBuilderRef builder, + unsigned length, + LLVMValueRef base_ptr, + LLVMValueRef offsets, + unsigned i) +{ + LLVMValueRef offset; + LLVMValueRef ptr; + + assert(LLVMTypeOf(base_ptr) == LLVMPointerType(LLVMInt8Type(), 0)); + + if (length == 1) { + assert(i == 0); + offset = offsets; + } else { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); + offset = LLVMBuildExtractElement(builder, offsets, index, ""); + } + + ptr = LLVMBuildGEP(builder, base_ptr, &offset, 1, ""); + + return ptr; +} + + +/** + * Gather one element from scatter positions in memory. + * + * @sa lp_build_gather() + */ +LLVMValueRef +lp_build_gather_elem(LLVMBuilderRef builder, + unsigned length, + unsigned src_width, + unsigned dst_width, + LLVMValueRef base_ptr, + LLVMValueRef offsets, + unsigned i) +{ + LLVMTypeRef src_type = LLVMIntType(src_width); + LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0); + LLVMTypeRef dst_elem_type = LLVMIntType(dst_width); + LLVMValueRef ptr; + LLVMValueRef res; + + assert(LLVMTypeOf(base_ptr) == LLVMPointerType(LLVMInt8Type(), 0)); + + ptr = lp_build_gather_elem_ptr(builder, length, base_ptr, offsets, i); + ptr = LLVMBuildBitCast(builder, ptr, src_ptr_type, ""); + res = LLVMBuildLoad(builder, ptr, ""); + + assert(src_width <= dst_width); + if (src_width > dst_width) + res = LLVMBuildTrunc(builder, res, dst_elem_type, ""); + if (src_width < dst_width) + res = LLVMBuildZExt(builder, res, dst_elem_type, ""); + + return res; +} + + +/** + * Gather elements from scatter positions in memory into a single vector. + * Use for fetching texels from a texture. + * For SSE, typical values are length=4, src_width=32, dst_width=32. + * + * @param length length of the offsets + * @param src_width src element width in bits + * @param dst_width result element width in bits (src will be expanded to fit) + * @param base_ptr base pointer, should be a i8 pointer type. + * @param offsets vector with offsets + */ +LLVMValueRef +lp_build_gather(LLVMBuilderRef builder, + unsigned length, + unsigned src_width, + unsigned dst_width, + LLVMValueRef base_ptr, + LLVMValueRef offsets) +{ + LLVMValueRef res; + + if (length == 1) { + /* Scalar */ + return lp_build_gather_elem(builder, length, + src_width, dst_width, + base_ptr, offsets, 0); + } else { + /* Vector */ + + LLVMTypeRef dst_elem_type = LLVMIntType(dst_width); + LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length); + unsigned i; + + res = LLVMGetUndef(dst_vec_type); + for (i = 0; i < length; ++i) { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); + LLVMValueRef elem; + elem = lp_build_gather_elem(builder, length, + src_width, dst_width, + base_ptr, offsets, i); + res = LLVMBuildInsertElement(builder, res, elem, index, ""); + } + } + + return res; +} diff --git a/src/gallium/auxiliary/gallivm/lp_bld_gather.h b/src/gallium/auxiliary/gallivm/lp_bld_gather.h new file mode 100644 index 0000000000..131af8ea07 --- /dev/null +++ b/src/gallium/auxiliary/gallivm/lp_bld_gather.h @@ -0,0 +1,61 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + + +#ifndef LP_BLD_GATHER_H_ +#define LP_BLD_GATHER_H_ + + +#include "gallivm/lp_bld.h" + + +LLVMValueRef +lp_build_gather_elem_ptr(LLVMBuilderRef builder, + unsigned length, + LLVMValueRef base_ptr, + LLVMValueRef offsets, + unsigned i); + +LLVMValueRef +lp_build_gather_elem(LLVMBuilderRef builder, + unsigned length, + unsigned src_width, + unsigned dst_width, + LLVMValueRef base_ptr, + LLVMValueRef offsets, + unsigned i); + +LLVMValueRef +lp_build_gather(LLVMBuilderRef builder, + unsigned length, + unsigned src_width, + unsigned dst_width, + LLVMValueRef base_ptr, + LLVMValueRef offsets); + + +#endif /* LP_BLD_GATHER_H_ */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c index 946c23e317..6e556f9d4e 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c @@ -124,57 +124,6 @@ lp_sampler_static_state(struct lp_sampler_static_state *state, } -/** - * Gather elements from scatter positions in memory into a single vector. - * Use for fetching texels from a texture. - * For SSE, typical values are length=4, src_width=32, dst_width=32. - * - * @param length length of the offsets - * @param src_width src element width in bits - * @param dst_width result element width in bits (src will be expanded to fit) - * @param base_ptr base pointer, should be a i8 pointer type. - * @param offsets vector with offsets - */ -LLVMValueRef -lp_build_gather(LLVMBuilderRef builder, - unsigned length, - unsigned src_width, - unsigned dst_width, - LLVMValueRef base_ptr, - LLVMValueRef offsets) -{ - LLVMTypeRef src_type = LLVMIntType(src_width); - LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0); - LLVMTypeRef dst_elem_type = LLVMIntType(dst_width); - LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length); - LLVMValueRef res; - unsigned i; - - res = LLVMGetUndef(dst_vec_type); - for(i = 0; i < length; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); - LLVMValueRef elem_offset; - LLVMValueRef elem_ptr; - LLVMValueRef elem; - - elem_offset = LLVMBuildExtractElement(builder, offsets, index, ""); - elem_ptr = LLVMBuildGEP(builder, base_ptr, &elem_offset, 1, ""); - elem_ptr = LLVMBuildBitCast(builder, elem_ptr, src_ptr_type, ""); - elem = LLVMBuildLoad(builder, elem_ptr, ""); - - assert(src_width <= dst_width); - if(src_width > dst_width) - elem = LLVMBuildTrunc(builder, elem, dst_elem_type, ""); - if(src_width < dst_width) - elem = LLVMBuildZExt(builder, elem, dst_elem_type, ""); - - res = LLVMBuildInsertElement(builder, res, elem, index, ""); - } - - return res; -} - - /** * Compute the offset of a pixel block. * diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h index 51e98ab2f9..64eb15a680 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h @@ -146,15 +146,6 @@ lp_sampler_static_state(struct lp_sampler_static_state *state, const struct pipe_sampler_state *sampler); -LLVMValueRef -lp_build_gather(LLVMBuilderRef builder, - unsigned length, - unsigned src_width, - unsigned dst_width, - LLVMValueRef base_ptr, - LLVMValueRef offsets); - - LLVMValueRef lp_build_sample_offset(struct lp_build_context *bld, const struct util_format_description *format_desc, diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c index 84c04fe272..a33231ddc4 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -50,6 +50,7 @@ #include "lp_bld_swizzle.h" #include "lp_bld_pack.h" #include "lp_bld_flow.h" +#include "lp_bld_gather.h" #include "lp_bld_format.h" #include "lp_bld_sample.h" -- cgit v1.2.3 From 01eebfe1b6de2e36dd3af0952fc8329b7073a100 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Mon, 14 Jun 2010 10:18:09 -0400 Subject: draw: implement vertex texture sampling using llvm --- src/gallium/auxiliary/Makefile | 3 +- src/gallium/auxiliary/SConscript | 3 +- src/gallium/auxiliary/draw/draw_context.c | 56 ++++++ src/gallium/auxiliary/draw/draw_context.h | 18 ++ src/gallium/auxiliary/draw/draw_llvm.c | 98 ++++++++-- src/gallium/auxiliary/draw/draw_llvm.h | 42 +++- src/gallium/auxiliary/draw/draw_llvm_sample.c | 216 +++++++++++++++++++++ src/gallium/auxiliary/draw/draw_private.h | 7 + .../draw/draw_pt_fetch_shade_pipeline_llvm.c | 5 +- src/gallium/drivers/llvmpipe/lp_screen.c | 2 +- src/gallium/drivers/llvmpipe/lp_setup.c | 73 ++++++- src/gallium/drivers/llvmpipe/lp_setup.h | 5 + src/gallium/drivers/llvmpipe/lp_setup_context.h | 4 + src/gallium/drivers/llvmpipe/lp_state_derived.c | 8 +- src/gallium/drivers/llvmpipe/lp_state_sampler.c | 8 + 15 files changed, 516 insertions(+), 32 deletions(-) create mode 100644 src/gallium/auxiliary/draw/draw_llvm_sample.c (limited to 'src/gallium/auxiliary/SConscript') diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index 91f8b1034a..731f60d216 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -171,7 +171,8 @@ GALLIVM_SOURCES = \ draw/draw_llvm.c \ draw/draw_vs_llvm.c \ draw/draw_pt_fetch_shade_pipeline_llvm.c \ - draw/draw_llvm_translate.c + draw/draw_llvm_translate.c \ + draw/draw_llvm_sample.c GALLIVM_CPP_SOURCES = \ gallivm/lp_bld_misc.cpp diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index af3f47bbf0..7e06cc0c76 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -221,7 +221,8 @@ if env['llvm']: 'draw/draw_llvm.c', 'draw/draw_pt_fetch_shade_pipeline_llvm.c', 'draw/draw_llvm_translate.c', - 'draw/draw_vs_llvm.c' + 'draw/draw_vs_llvm.c', + 'draw/draw_llvm_sample.c' ] gallium = env.ConvenienceLibrary( diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index dab95e5051..aac1ed602c 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -40,6 +40,7 @@ #if HAVE_LLVM #include "gallivm/lp_bld_init.h" +#include "draw_llvm.h" #endif struct draw_context *draw_create( struct pipe_context *pipe ) @@ -52,6 +53,7 @@ struct draw_context *draw_create( struct pipe_context *pipe ) lp_build_init(); assert(lp_build_engine); draw->engine = lp_build_engine; + draw->llvm = draw_llvm_create(draw); #endif if (!draw_init(draw)) @@ -132,6 +134,9 @@ void draw_destroy( struct draw_context *draw ) draw_pt_destroy( draw ); draw_vs_destroy( draw ); draw_gs_destroy( draw ); +#ifdef HAVE_LLVM + draw_llvm_destroy( draw->llvm ); +#endif FREE( draw ); } @@ -601,3 +606,54 @@ draw_set_so_state(struct draw_context *draw, state, sizeof(struct pipe_stream_output_state)); } + +void +draw_set_sampler_views(struct draw_context *draw, + struct pipe_sampler_view **views, + unsigned num) +{ + unsigned i; + + debug_assert(num <= PIPE_MAX_VERTEX_SAMPLERS); + + for (i = 0; i < num; ++i) + draw->sampler_views[i] = views[i]; + for (i = num; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) + draw->sampler_views[i] = NULL; + + draw->num_sampler_views = num; +} + +void +draw_set_samplers(struct draw_context *draw, + struct pipe_sampler_state **samplers, + unsigned num) +{ + unsigned i; + + debug_assert(num <= PIPE_MAX_VERTEX_SAMPLERS); + + for (i = 0; i < num; ++i) + draw->samplers[i] = samplers[i]; + for (i = num; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) + draw->samplers[i] = NULL; + + draw->num_samplers = num; +} + +void +draw_set_mapped_texture(struct draw_context *draw, + unsigned sampler_idx, + uint32_t width, uint32_t height, uint32_t depth, + uint32_t last_level, + uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS], + uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS], + const void *data[DRAW_MAX_TEXTURE_LEVELS]) +{ +#ifdef HAVE_LLVM + draw_llvm_set_mapped_texture(draw, + sampler_idx, + width, height, depth, last_level, + row_stride, img_stride, data); +#endif +} diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h index c0122f2aca..724f992783 100644 --- a/src/gallium/auxiliary/draw/draw_context.h +++ b/src/gallium/auxiliary/draw/draw_context.h @@ -47,6 +47,7 @@ struct draw_vertex_shader; struct draw_geometry_shader; struct tgsi_sampler; +#define DRAW_MAX_TEXTURE_LEVELS 13 /* 4K x 4K for now */ struct draw_context *draw_create( struct pipe_context *pipe ); @@ -101,6 +102,23 @@ draw_texture_samplers(struct draw_context *draw, uint num_samplers, struct tgsi_sampler **samplers); +void +draw_set_sampler_views(struct draw_context *draw, + struct pipe_sampler_view **views, + unsigned num); +void +draw_set_samplers(struct draw_context *draw, + struct pipe_sampler_state **samplers, + unsigned num); + +void +draw_set_mapped_texture(struct draw_context *draw, + unsigned sampler_idx, + uint32_t width, uint32_t height, uint32_t depth, + uint32_t last_level, + uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS], + uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS], + const void *data[DRAW_MAX_TEXTURE_LEVELS]); /* diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index f521669fcd..42653d36ec 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -42,14 +42,13 @@ #include "tgsi/tgsi_dump.h" #include "util/u_cpu_detect.h" -#include "util/u_string.h" #include "util/u_pointer.h" +#include "util/u_string.h" #include #define DEBUG_STORE 0 - /* generates the draw jit function */ static void draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *var); @@ -63,12 +62,19 @@ init_globals(struct draw_llvm *llvm) /* struct draw_jit_texture */ { - LLVMTypeRef elem_types[4]; + LLVMTypeRef elem_types[DRAW_JIT_TEXTURE_NUM_FIELDS]; elem_types[DRAW_JIT_TEXTURE_WIDTH] = LLVMInt32Type(); elem_types[DRAW_JIT_TEXTURE_HEIGHT] = LLVMInt32Type(); - elem_types[DRAW_JIT_TEXTURE_STRIDE] = LLVMInt32Type(); - elem_types[DRAW_JIT_TEXTURE_DATA] = LLVMPointerType(LLVMInt8Type(), 0); + elem_types[DRAW_JIT_TEXTURE_DEPTH] = LLVMInt32Type(); + elem_types[DRAW_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32Type(); + elem_types[DRAW_JIT_TEXTURE_ROW_STRIDE] = + LLVMArrayType(LLVMInt32Type(), DRAW_MAX_TEXTURE_LEVELS); + elem_types[DRAW_JIT_TEXTURE_IMG_STRIDE] = + LLVMArrayType(LLVMInt32Type(), DRAW_MAX_TEXTURE_LEVELS); + elem_types[DRAW_JIT_TEXTURE_DATA] = + LLVMArrayType(LLVMPointerType(LLVMInt8Type(), 0), + DRAW_MAX_TEXTURE_LEVELS); texture_type = LLVMStructType(elem_types, Elements(elem_types), 0); @@ -78,9 +84,18 @@ init_globals(struct draw_llvm *llvm) LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, height, llvm->target, texture_type, DRAW_JIT_TEXTURE_HEIGHT); - LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, stride, + LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, depth, + llvm->target, texture_type, + DRAW_JIT_TEXTURE_DEPTH); + LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, last_level, + llvm->target, texture_type, + DRAW_JIT_TEXTURE_LAST_LEVEL); + LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, row_stride, llvm->target, texture_type, - DRAW_JIT_TEXTURE_STRIDE); + DRAW_JIT_TEXTURE_ROW_STRIDE); + LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, img_stride, + llvm->target, texture_type, + DRAW_JIT_TEXTURE_IMG_STRIDE); LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, data, llvm->target, texture_type, DRAW_JIT_TEXTURE_DATA); @@ -98,7 +113,8 @@ init_globals(struct draw_llvm *llvm) elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* vs_constants */ elem_types[1] = LLVMPointerType(LLVMFloatType(), 0); /* vs_constants */ - elem_types[2] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */ + elem_types[2] = LLVMArrayType(texture_type, + PIPE_MAX_VERTEX_SAMPLERS); /* textures */ context_type = LLVMStructType(elem_types, Elements(elem_types), 0); @@ -108,7 +124,7 @@ init_globals(struct draw_llvm *llvm) llvm->target, context_type, 1); LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, textures, llvm->target, context_type, - DRAW_JIT_CONTEXT_TEXTURES_INDEX); + DRAW_JIT_CTX_TEXTURES); LP_CHECK_STRUCT_SIZE(struct draw_jit_context, llvm->target, context_type); @@ -290,7 +306,8 @@ generate_vs(struct draw_llvm *llvm, LLVMBuilderRef builder, LLVMValueRef (*outputs)[NUM_CHANNELS], const LLVMValueRef (*inputs)[NUM_CHANNELS], - LLVMValueRef context_ptr) + LLVMValueRef context_ptr, + struct lp_build_sampler_soa *sampler) { const struct tgsi_token *tokens = llvm->draw->vs.vertex_shader->state.tokens; struct lp_type vs_type; @@ -318,7 +335,7 @@ generate_vs(struct draw_llvm *llvm, NULL /*pos*/, inputs, outputs, - NULL/*sampler*/, + sampler, &llvm->draw->vs.vertex_shader->info); } @@ -641,6 +658,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) const int max_vertices = 4; LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS]; void *code; + struct lp_build_sampler_soa *sampler = 0; arg_types[0] = llvm->context_ptr_type; /* context */ arg_types[1] = llvm->vertex_header_ptr_type; /* vertex_header */ @@ -688,6 +706,10 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) step = LLVMConstInt(LLVMInt32Type(), max_vertices, 0); + /* code generated texture sampling */ + sampler = draw_llvm_sampler_soa_create(variant->key.sampler, + context_ptr); + #if DEBUG_STORE lp_build_printf(builder, "start = %d, end = %d, step = %d\n", start, end, step); @@ -729,7 +751,8 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) builder, outputs, ptr_aos, - context_ptr); + context_ptr, + sampler); convert_to_aos(builder, io, outputs, draw->vs.vertex_shader->info.num_outputs, @@ -737,6 +760,8 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) } lp_build_loop_end_cond(builder, end, step, LLVMIntUGE, &lp_loop); + sampler->destroy(sampler); + LLVMBuildRetVoid(builder); LLVMDisposeBuilder(builder); @@ -787,6 +812,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS]; LLVMValueRef fetch_max; void *code; + struct lp_build_sampler_soa *sampler = 0; arg_types[0] = llvm->context_ptr_type; /* context */ arg_types[1] = llvm->vertex_header_ptr_type; /* vertex_header */ @@ -833,6 +859,10 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian step = LLVMConstInt(LLVMInt32Type(), max_vertices, 0); + /* code generated texture sampling */ + sampler = draw_llvm_sampler_soa_create(variant->key.sampler, + context_ptr); + fetch_max = LLVMBuildSub(builder, fetch_count, LLVMConstInt(LLVMInt32Type(), 1, 0), "fetch_max"); @@ -884,7 +914,8 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian builder, outputs, ptr_aos, - context_ptr); + context_ptr, + sampler); convert_to_aos(builder, io, outputs, draw->vs.vertex_shader->info.num_outputs, @@ -892,6 +923,8 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian } lp_build_loop_end_cond(builder, fetch_count, step, LLVMIntUGE, &lp_loop); + sampler->destroy(sampler); + LLVMBuildRetVoid(builder); LLVMDisposeBuilder(builder); @@ -925,6 +958,8 @@ void draw_llvm_make_variant_key(struct draw_llvm *llvm, struct draw_llvm_variant_key *key) { + unsigned i; + memset(key, 0, sizeof(struct draw_llvm_variant_key)); key->nr_vertex_elements = llvm->draw->pt.nr_vertex_elements; @@ -936,6 +971,43 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm, memcpy(&key->vs, &llvm->draw->vs.vertex_shader->state, sizeof(struct pipe_shader_state)); + + for(i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) { + struct draw_vertex_shader *shader = llvm->draw->vs.vertex_shader; + if(shader->info.file_mask[TGSI_FILE_SAMPLER] & (1 << i)) + lp_sampler_static_state(&key->sampler[i], + llvm->draw->sampler_views[i], + llvm->draw->samplers[i]); + } +} + +void +draw_llvm_set_mapped_texture(struct draw_context *draw, + unsigned sampler_idx, + uint32_t width, uint32_t height, uint32_t depth, + uint32_t last_level, + uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS], + uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS], + const void *data[DRAW_MAX_TEXTURE_LEVELS]) +{ + unsigned j; + struct draw_jit_texture *jit_tex; + + assert(sampler_idx <= PIPE_MAX_VERTEX_SAMPLERS); + + + jit_tex = &draw->llvm->jit_context.textures[sampler_idx]; + + jit_tex->width = width; + jit_tex->height = height; + jit_tex->depth = depth; + jit_tex->last_level = last_level; + + for (j = 0; j <= last_level; j++) { + jit_tex->data[j] = data[j]; + jit_tex->row_stride[j] = row_stride[j]; + jit_tex->img_stride[j] = img_stride[j]; + } } void diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h index 1ef009b592..05446517c6 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.h +++ b/src/gallium/auxiliary/draw/draw_llvm.h @@ -25,12 +25,13 @@ * **************************************************************************/ -#ifndef HAVE_LLVM_H -#define HAVE_LLVM_H +#ifndef DRAW_LLVM_H +#define DRAW_LLVM_H #include "draw/draw_private.h" #include "draw/draw_vs.h" +#include "gallivm/lp_bld_sample.h" #include "pipe/p_context.h" #include "util/u_simple_list.h" @@ -40,6 +41,8 @@ #include #include +#define DRAW_MAX_TEXTURE_LEVELS 13 /* 4K x 4K for now */ + struct draw_llvm; struct llvm_vertex_shader; @@ -47,15 +50,22 @@ struct draw_jit_texture { uint32_t width; uint32_t height; - uint32_t stride; - const void *data; + uint32_t depth; + uint32_t last_level; + uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS]; + uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS]; + const void *data[DRAW_MAX_TEXTURE_LEVELS]; }; enum { DRAW_JIT_TEXTURE_WIDTH = 0, DRAW_JIT_TEXTURE_HEIGHT, - DRAW_JIT_TEXTURE_STRIDE, - DRAW_JIT_TEXTURE_DATA + DRAW_JIT_TEXTURE_DEPTH, + DRAW_JIT_TEXTURE_LAST_LEVEL, + DRAW_JIT_TEXTURE_ROW_STRIDE, + DRAW_JIT_TEXTURE_IMG_STRIDE, + DRAW_JIT_TEXTURE_DATA, + DRAW_JIT_TEXTURE_NUM_FIELDS /* number of fields above */ }; enum { @@ -81,7 +91,7 @@ struct draw_jit_context const float *gs_constants; - struct draw_jit_texture textures[PIPE_MAX_SAMPLERS]; + struct draw_jit_texture textures[PIPE_MAX_VERTEX_SAMPLERS]; }; @@ -91,10 +101,10 @@ struct draw_jit_context #define draw_jit_context_gs_constants(_builder, _ptr) \ lp_build_struct_get(_builder, _ptr, 1, "gs_constants") -#define DRAW_JIT_CONTEXT_TEXTURES_INDEX 2 +#define DRAW_JIT_CTX_TEXTURES 2 #define draw_jit_context_textures(_builder, _ptr) \ - lp_build_struct_get_ptr(_builder, _ptr, DRAW_JIT_CONTEXT_TEXTURES_INDEX, "textures") + lp_build_struct_get_ptr(_builder, _ptr, DRAW_JIT_CTX_TEXTURES, "textures") @@ -142,6 +152,7 @@ struct draw_llvm_variant_key struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; unsigned nr_vertex_elements; struct pipe_shader_state vs; + struct lp_sampler_static_state sampler[PIPE_MAX_VERTEX_SAMPLERS]; }; struct draw_llvm_variant_list_item @@ -221,4 +232,17 @@ draw_llvm_translate_from(LLVMBuilderRef builder, LLVMValueRef vbuffer, enum pipe_format from_format); +struct lp_build_sampler_soa * +draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, + LLVMValueRef context_ptr); + +void +draw_llvm_set_mapped_texture(struct draw_context *draw, + unsigned sampler_idx, + uint32_t width, uint32_t height, uint32_t depth, + uint32_t last_level, + uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS], + uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS], + const void *data[DRAW_MAX_TEXTURE_LEVELS]); + #endif diff --git a/src/gallium/auxiliary/draw/draw_llvm_sample.c b/src/gallium/auxiliary/draw/draw_llvm_sample.c new file mode 100644 index 0000000000..2613224f75 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_llvm_sample.c @@ -0,0 +1,216 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * Texture sampling code generation + * @author Jose Fonseca + */ + +#include "pipe/p_defines.h" +#include "pipe/p_shader_tokens.h" +#include "gallivm/lp_bld_debug.h" +#include "gallivm/lp_bld_type.h" +#include "gallivm/lp_bld_sample.h" +#include "gallivm/lp_bld_tgsi.h" + + +#include "util/u_cpu_detect.h" +#include "util/u_debug.h" +#include "util/u_memory.h" +#include "util/u_pointer.h" +#include "util/u_string.h" + +#include "draw_llvm.h" + + +/** + * This provides the bridge between the sampler state store in + * lp_jit_context and lp_jit_texture and the sampler code + * generator. It provides the texture layout information required by + * the texture sampler code generator in terms of the state stored in + * lp_jit_context and lp_jit_texture in runtime. + */ +struct draw_llvm_sampler_dynamic_state +{ + struct lp_sampler_dynamic_state base; + + const struct lp_sampler_static_state *static_state; + + LLVMValueRef context_ptr; +}; + + +/** + * This is the bridge between our sampler and the TGSI translator. + */ +struct draw_llvm_sampler_soa +{ + struct lp_build_sampler_soa base; + + struct draw_llvm_sampler_dynamic_state dynamic_state; +}; + + +/** + * Fetch the specified member of the lp_jit_texture structure. + * \param emit_load if TRUE, emit the LLVM load instruction to actually + * fetch the field's value. Otherwise, just emit the + * GEP code to address the field. + * + * @sa http://llvm.org/docs/GetElementPtr.html + */ +static LLVMValueRef +draw_llvm_texture_member(const struct lp_sampler_dynamic_state *base, + LLVMBuilderRef builder, + unsigned unit, + unsigned member_index, + const char *member_name, + boolean emit_load) +{ + struct draw_llvm_sampler_dynamic_state *state = + (struct draw_llvm_sampler_dynamic_state *)base; + LLVMValueRef indices[4]; + LLVMValueRef ptr; + LLVMValueRef res; + + debug_assert(unit < PIPE_MAX_VERTEX_SAMPLERS); + + /* context[0] */ + indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0); + /* context[0].textures */ + indices[1] = LLVMConstInt(LLVMInt32Type(), DRAW_JIT_CTX_TEXTURES, 0); + /* context[0].textures[unit] */ + indices[2] = LLVMConstInt(LLVMInt32Type(), unit, 0); + /* context[0].textures[unit].member */ + indices[3] = LLVMConstInt(LLVMInt32Type(), member_index, 0); + + ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), ""); + + if (emit_load) + res = LLVMBuildLoad(builder, ptr, ""); + else + res = ptr; + + lp_build_name(res, "context.texture%u.%s", unit, member_name); + + return res; +} + + +/** + * Helper macro to instantiate the functions that generate the code to + * fetch the members of lp_jit_texture to fulfill the sampler code + * generator requests. + * + * This complexity is the price we have to pay to keep the texture + * sampler code generator a reusable module without dependencies to + * llvmpipe internals. + */ +#define DRAW_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \ + static LLVMValueRef \ + draw_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \ + LLVMBuilderRef builder, \ + unsigned unit) \ + { \ + return draw_llvm_texture_member(base, builder, unit, _index, #_name, _emit_load ); \ + } + + +DRAW_LLVM_TEXTURE_MEMBER(width, DRAW_JIT_TEXTURE_WIDTH, TRUE) +DRAW_LLVM_TEXTURE_MEMBER(height, DRAW_JIT_TEXTURE_HEIGHT, TRUE) +DRAW_LLVM_TEXTURE_MEMBER(depth, DRAW_JIT_TEXTURE_DEPTH, TRUE) +DRAW_LLVM_TEXTURE_MEMBER(last_level, DRAW_JIT_TEXTURE_LAST_LEVEL, TRUE) +DRAW_LLVM_TEXTURE_MEMBER(row_stride, DRAW_JIT_TEXTURE_ROW_STRIDE, FALSE) +DRAW_LLVM_TEXTURE_MEMBER(img_stride, DRAW_JIT_TEXTURE_IMG_STRIDE, FALSE) +DRAW_LLVM_TEXTURE_MEMBER(data_ptr, DRAW_JIT_TEXTURE_DATA, FALSE) + + +static void +draw_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler) +{ + FREE(sampler); +} + + +/** + * Fetch filtered values from texture. + * The 'texel' parameter returns four vectors corresponding to R, G, B, A. + */ +static void +draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, + LLVMBuilderRef builder, + struct lp_type type, + unsigned unit, + unsigned num_coords, + const LLVMValueRef *coords, + const LLVMValueRef *ddx, + const LLVMValueRef *ddy, + LLVMValueRef lod_bias, /* optional */ + LLVMValueRef explicit_lod, /* optional */ + LLVMValueRef *texel) +{ + struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base; + + assert(unit < PIPE_MAX_VERTEX_SAMPLERS); + + lp_build_sample_soa(builder, + &sampler->dynamic_state.static_state[unit], + &sampler->dynamic_state.base, + type, + unit, + num_coords, coords, + ddx, ddy, + lod_bias, explicit_lod, + texel); +} + + +struct lp_build_sampler_soa * +draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, + LLVMValueRef context_ptr) +{ + struct draw_llvm_sampler_soa *sampler; + + sampler = CALLOC_STRUCT(draw_llvm_sampler_soa); + if(!sampler) + return NULL; + + sampler->base.destroy = draw_llvm_sampler_soa_destroy; + sampler->base.emit_fetch_texel = draw_llvm_sampler_soa_emit_fetch_texel; + sampler->dynamic_state.base.width = draw_llvm_texture_width; + sampler->dynamic_state.base.height = draw_llvm_texture_height; + sampler->dynamic_state.base.depth = draw_llvm_texture_depth; + sampler->dynamic_state.base.last_level = draw_llvm_texture_last_level; + sampler->dynamic_state.base.row_stride = draw_llvm_texture_row_stride; + sampler->dynamic_state.base.img_stride = draw_llvm_texture_img_stride; + sampler->dynamic_state.base.data_ptr = draw_llvm_texture_data_ptr; + sampler->dynamic_state.static_state = static_state; + sampler->dynamic_state.context_ptr = context_ptr; + + return &sampler->base; +} + diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index 54944a7c67..8af885908e 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -48,6 +48,7 @@ #ifdef HAVE_LLVM #include +struct draw_llvm; #endif @@ -262,9 +263,15 @@ struct draw_context unsigned instance_id; #ifdef HAVE_LLVM + struct draw_llvm *llvm; LLVMExecutionEngineRef engine; #endif + struct pipe_sampler_view *sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; + unsigned num_sampler_views; + const struct pipe_sampler_state *samplers[PIPE_MAX_VERTEX_SAMPLERS]; + unsigned num_samplers; + void *driver_private; }; diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c index d33969ac70..6aefbede59 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c @@ -392,9 +392,6 @@ static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle ) if (fpme->post_vs) draw_pt_post_vs_destroy( fpme->post_vs ); - if (fpme->llvm) - draw_llvm_destroy( fpme->llvm ); - FREE(middle); } @@ -436,7 +433,7 @@ draw_pt_fetch_pipeline_or_emit_llvm(struct draw_context *draw) if (!fpme->so_emit) goto fail; - fpme->llvm = draw_llvm_create(draw); + fpme->llvm = draw->llvm; if (!fpme->llvm) goto fail; diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 49b13f464a..edcab0f8d9 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -86,7 +86,7 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: return PIPE_MAX_SAMPLERS; case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: - return 0; + return PIPE_MAX_VERTEX_SAMPLERS; case PIPE_CAP_MAX_COMBINED_SAMPLERS: return PIPE_MAX_SAMPLERS + PIPE_MAX_VERTEX_SAMPLERS; case PIPE_CAP_NPOT_TEXTURES: diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 2597fa8f71..fcb6e06123 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -641,7 +641,6 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, /* * XXX: Where should this be unmapped? */ - struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); struct sw_winsys *winsys = screen->winsys; jit_tex->data[0] = winsys->displaytarget_map(winsys, lp_tex->dt, @@ -657,6 +656,75 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, } +/** + * Called during state validation when LP_NEW_SAMPLER_VIEW is set. + */ +void +lp_setup_set_vertex_sampler_views(struct lp_setup_context *setup, + unsigned num, + struct pipe_sampler_view **views) +{ + unsigned i; + uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS]; + uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS]; + const void *data[DRAW_MAX_TEXTURE_LEVELS]; + struct lp_scene *scene; + struct llvmpipe_context *lp; + + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); + + assert(num <= PIPE_MAX_VERTEX_SAMPLERS); + + scene = lp_setup_get_current_scene(setup); + lp = llvmpipe_context(scene->pipe); + + for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { + struct pipe_sampler_view *view = i < num ? views[i] : NULL; + + if (view) { + struct pipe_resource *tex = view->texture; + struct llvmpipe_resource *lp_tex = llvmpipe_resource(tex); + + /* We're referencing the texture's internal data, so save a + * reference to it. + */ + pipe_resource_reference(&setup->vs.current_tex[i], tex); + + if (!lp_tex->dt) { + /* regular texture - setup array of mipmap level pointers */ + int j; + for (j = 0; j <= tex->last_level; j++) { + data[j] = + llvmpipe_get_texture_image_all(lp_tex, j, LP_TEX_USAGE_READ, + LP_TEX_LAYOUT_LINEAR); + row_stride[j] = lp_tex->row_stride[j]; + img_stride[j] = lp_tex->img_stride[j]; + } + } + else { + /* display target texture/surface */ + /* + * XXX: Where should this be unmapped? + */ + struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); + struct sw_winsys *winsys = screen->winsys; + data[0] = winsys->displaytarget_map(winsys, lp_tex->dt, + PIPE_TRANSFER_READ); + row_stride[0] = lp_tex->row_stride[0]; + img_stride[0] = lp_tex->img_stride[0]; + assert(data[0]); + } + draw_set_mapped_texture(lp->draw, + i, + tex->width0, tex->height0, tex->depth0, + tex->last_level, + row_stride, img_stride, data); + } + } +} + + + /** * Is the given texture referenced by any scene? * Note: we have to check all scenes including any scenes currently @@ -850,6 +918,9 @@ lp_setup_destroy( struct lp_setup_context *setup ) util_unreference_framebuffer_state(&setup->fb); + for (i = 0; i < Elements(setup->vs.current_tex); i++) { + pipe_resource_reference(&setup->vs.current_tex[i], NULL); + } for (i = 0; i < Elements(setup->fs.current_tex); i++) { pipe_resource_reference(&setup->fs.current_tex[i], NULL); } diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h index 6a0dc55129..fd2c927c2e 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -133,6 +133,11 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, unsigned num, struct pipe_sampler_view **views); +void +lp_setup_set_vertex_sampler_views(struct lp_setup_context *setup, + unsigned num, + struct pipe_sampler_view **views); + unsigned lp_setup_is_resource_referenced( const struct lp_setup_context *setup, const struct pipe_resource *texture ); diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index 8f4e00f073..947d5efe2b 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -116,6 +116,10 @@ struct lp_setup_context struct pipe_resource *current_tex[PIPE_MAX_SAMPLERS]; } fs; + struct { + struct pipe_resource *current_tex[PIPE_MAX_VERTEX_SAMPLERS]; + } vs; + /** fragment shader constants */ struct { struct pipe_resource *current; diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index d20a5218d4..263b117494 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -188,10 +188,14 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) lp_setup_set_fs_constants(llvmpipe->setup, llvmpipe->constants[PIPE_SHADER_FRAGMENT][0]); - if (llvmpipe->dirty & LP_NEW_SAMPLER_VIEW) - lp_setup_set_fragment_sampler_views(llvmpipe->setup, + if (llvmpipe->dirty & LP_NEW_SAMPLER_VIEW) { + lp_setup_set_fragment_sampler_views(llvmpipe->setup, llvmpipe->num_fragment_sampler_views, llvmpipe->fragment_sampler_views); + lp_setup_set_vertex_sampler_views(llvmpipe->setup, + llvmpipe->num_vertex_sampler_views, + llvmpipe->vertex_sampler_views); + } llvmpipe->dirty = 0; } diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c b/src/gallium/drivers/llvmpipe/lp_state_sampler.c index e94065fb6a..0fea7f20a7 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_sampler.c +++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c @@ -100,6 +100,10 @@ llvmpipe_bind_vertex_sampler_states(struct pipe_context *pipe, llvmpipe->num_vertex_samplers = num_samplers; + draw_set_samplers(llvmpipe->draw, + llvmpipe->vertex_samplers, + llvmpipe->num_vertex_samplers); + llvmpipe->dirty |= LP_NEW_SAMPLER; } @@ -166,6 +170,10 @@ llvmpipe_set_vertex_sampler_views(struct pipe_context *pipe, llvmpipe->num_vertex_sampler_views = num; + draw_set_sampler_views(llvmpipe->draw, + llvmpipe->vertex_sampler_views, + llvmpipe->num_vertex_sampler_views); + llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW; } -- cgit v1.2.3 From 5cf0789f91354b00c055825c2764b14ce1ba09a9 Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Fri, 16 Jul 2010 12:34:22 -0700 Subject: scons: Fix Cygwin build. The Cygwin SCons build needed several file names to be fully qualified. --- src/gallium/auxiliary/SConscript | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/gallium/auxiliary/SConscript') diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index 7e06cc0c76..926b2651da 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -32,8 +32,8 @@ env.CodeGenerate( env.CodeGenerate( target = 'util/u_format_table.c', - script = 'util/u_format_table.py', - source = ['util/u_format.csv'], + script = '#src/gallium/auxiliary/util/u_format_table.py', + source = ['#src/gallium/auxiliary/util/u_format.csv'], command = 'python $SCRIPT $SOURCE > $TARGET' ) @@ -45,7 +45,7 @@ env.CodeGenerate( ) env.Depends('util/u_format_table.c', [ - 'util/u_format_parse.py', + '#src/gallium/auxiliary/util/u_format_parse.py', 'util/u_format_pack.py', ]) -- cgit v1.2.3 From ad44b775e30b2740d25bb8330c9e8879f1ec5533 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Mon, 19 Jul 2010 11:04:30 +0200 Subject: util: add a memory pool for equally sized memory allocations malloc/free are in O(1). --- src/gallium/auxiliary/Makefile | 1 + src/gallium/auxiliary/SConscript | 1 + src/gallium/auxiliary/util/u_mempool.c | 173 +++++++++++++++++++++++++++++++++ src/gallium/auxiliary/util/u_mempool.h | 92 ++++++++++++++++++ 4 files changed, 267 insertions(+) create mode 100644 src/gallium/auxiliary/util/u_mempool.c create mode 100644 src/gallium/auxiliary/util/u_mempool.h (limited to 'src/gallium/auxiliary/SConscript') diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index 731f60d216..dcebab7c0f 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -124,6 +124,7 @@ C_SOURCES = \ util/u_linear.c \ util/u_network.c \ util/u_math.c \ + util/u_mempool.c \ util/u_mm.c \ util/u_rect.c \ util/u_ringbuffer.c \ diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index 926b2651da..72a16617db 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -172,6 +172,7 @@ source = [ 'util/u_keymap.c', 'util/u_network.c', 'util/u_math.c', + 'util/u_mempool.c', 'util/u_mm.c', 'util/u_rect.c', 'util/u_resource.c', diff --git a/src/gallium/auxiliary/util/u_mempool.c b/src/gallium/auxiliary/util/u_mempool.c new file mode 100644 index 0000000000..da1cc702ec --- /dev/null +++ b/src/gallium/auxiliary/util/u_mempool.c @@ -0,0 +1,173 @@ +/* + * Copyright 2010 Marek Olšák + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "util/u_mempool.h" + +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" + +#include + +#define UTIL_MEMPOOL_MAGIC 0xcafe4321 + +struct util_mempool_block_body {}; + +/* The block is either allocated memory or free space. */ +struct util_mempool_block { + /* The header. */ + /* The first next free block. */ + struct util_mempool_block *next_free; + + intptr_t magic; + + /* The block begins here. */ + struct util_mempool_block_body body; + + /* Memory after the last member is dedicated to the block itself. + * The allocated size is always larger than this structure. */ +}; + +static struct util_mempool_block * +util_mempool_get_block(struct util_mempool *pool, + struct util_mempool_page *page, unsigned index) +{ + return (struct util_mempool_block*) + ((uint8_t*)&page->body + (pool->block_size * index)); +} + +static void util_mempool_add_new_page(struct util_mempool *pool) +{ + struct util_mempool_page *page; + struct util_mempool_block *block; + int i; + + page = MALLOC(pool->page_size); + insert_at_tail(&pool->list, page); + + /* Mark all blocks as free. */ + for (i = 0; i < pool->num_blocks-1; i++) { + block = util_mempool_get_block(pool, page, i); + block->next_free = util_mempool_get_block(pool, page, i+1); + block->magic = UTIL_MEMPOOL_MAGIC; + } + + block = util_mempool_get_block(pool, page, pool->num_blocks-1); + block->next_free = pool->first_free; + pool->first_free = util_mempool_get_block(pool, page, 0); + pool->num_pages++; + +#if 0 + fprintf(stderr, "New page! Num of pages: %i\n", pool->num_pages); +#endif +} + +static void *util_mempool_malloc_st(struct util_mempool *pool) +{ + struct util_mempool_block *block; + + if (!pool->first_free) + util_mempool_add_new_page(pool); + + block = pool->first_free; + assert(block->magic == UTIL_MEMPOOL_MAGIC); + pool->first_free = block->next_free; + + return &block->body; +} + +static void util_mempool_free_st(struct util_mempool *pool, void *ptr) +{ + struct util_mempool_block dummy; + struct util_mempool_block *block = + (struct util_mempool_block*) + ((uint8_t*)ptr - ((uint8_t*)&dummy.body - (uint8_t*)&dummy)); + + assert(block->magic == UTIL_MEMPOOL_MAGIC); + block->next_free = pool->first_free; + pool->first_free = block; +} + +static void *util_mempool_malloc_mt(struct util_mempool *pool) +{ + void *mem; + + pipe_mutex_lock(pool->mutex); + mem = util_mempool_malloc_st(pool); + pipe_mutex_unlock(pool->mutex); + return mem; +} + +static void util_mempool_free_mt(struct util_mempool *pool, void *ptr) +{ + pipe_mutex_lock(pool->mutex); + util_mempool_free_st(pool, ptr); + pipe_mutex_unlock(pool->mutex); +} + +void util_mempool_set_thread_safety(struct util_mempool *pool, + enum util_mempool_threading threading) +{ + pool->threading = threading; + + if (threading) { + pipe_mutex_init(pool->mutex); + pool->malloc = util_mempool_malloc_mt; + pool->free = util_mempool_free_mt; + } else { + pool->malloc = util_mempool_malloc_st; + pool->free = util_mempool_free_st; + } +} + +void util_mempool_create(struct util_mempool *pool, + unsigned item_size, + unsigned num_blocks, + enum util_mempool_threading threading) +{ + item_size = align(item_size, sizeof(intptr_t)); + + pool->num_pages = 0; + pool->num_blocks = num_blocks; + pool->block_size = sizeof(struct util_mempool_block) + item_size; + pool->block_size = align(pool->block_size, sizeof(intptr_t)); + pool->page_size = sizeof(struct util_mempool_page) + + num_blocks * pool->block_size; + pool->first_free = NULL; + + make_empty_list(&pool->list); + + util_mempool_set_thread_safety(pool, threading); +} + +void util_mempool_destroy(struct util_mempool *pool) +{ + struct util_mempool_page *page, *temp; + + foreach_s(page, temp, &pool->list) { + remove_from_list(page); + FREE(page); + } + + if (pool->threading) + pipe_mutex_destroy(pool->mutex); +} diff --git a/src/gallium/auxiliary/util/u_mempool.h b/src/gallium/auxiliary/util/u_mempool.h new file mode 100644 index 0000000000..b8d2aaefb6 --- /dev/null +++ b/src/gallium/auxiliary/util/u_mempool.h @@ -0,0 +1,92 @@ +/* + * Copyright 2010 Marek Olšák + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/** + * @file + * Simple memory pool for equally sized memory allocations. + * util_mempool_malloc and util_mempool_free are in O(1). + * + * Good for allocations which have very low lifetime and are allocated + * and freed very often. Use a profiler first! + * + * Candidates: get_transfer, user_buffer_create + * + * @author Marek Olšák + */ + +#ifndef U_MEMPOOL_H +#define U_MEMPOOL_H + +#include "os/os_thread.h" + +enum util_mempool_threading { + UTIL_MEMPOOL_SINGLETHREADED = FALSE, + UTIL_MEMPOOL_MULTITHREADED = TRUE +}; + +struct util_mempool_page_body {}; + +/* The page is an array of blocks (allocations). */ +struct util_mempool_page { + /* The header (linked-list pointers). */ + struct util_mempool_page *prev, *next; + + /* The page begins here. */ + struct util_mempool_page_body body; + + /* Memory after the last member is dedicated to the page itself. + * The allocated size is always larger than this structure. */ +}; + +struct util_mempool { + /* Public members. */ + void *(*malloc)(struct util_mempool *pool); + void (*free)(struct util_mempool *pool, void *ptr); + + /* Private members. */ + struct util_mempool_block *first_free; + + struct util_mempool_page list; + + unsigned block_size; + unsigned page_size; + unsigned num_blocks; + unsigned num_pages; + enum util_mempool_threading threading; + + pipe_mutex mutex; +}; + +void util_mempool_create(struct util_mempool *pool, + unsigned item_size, + unsigned num_blocks, + enum util_mempool_threading threading); + +void util_mempool_destroy(struct util_mempool *pool); + +void util_mempool_set_thread_safety(struct util_mempool *pool, + enum util_mempool_threading threading); + +#define util_mempool_malloc(pool) (pool)->malloc(pool) +#define util_mempool_free(pool, ptr) (pool)->free(pool, ptr) + +#endif -- cgit v1.2.3