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/draw/draw_llvm.c | 69 +++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) (limited to 'src/gallium/auxiliary/draw/draw_llvm.c') diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 9117c1303d..f521669fcd 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -1,3 +1,30 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + #include "draw_llvm.h" #include "draw_context.h" @@ -219,6 +246,9 @@ draw_llvm_create(struct draw_context *draw) LLVMDumpModule(llvm->module); } + llvm->nr_variants = 0; + make_empty_list(&llvm->vs_variants_list); + return llvm; } @@ -231,9 +261,13 @@ draw_llvm_destroy(struct draw_llvm *llvm) } struct draw_llvm_variant * -draw_llvm_prepare(struct draw_llvm *llvm, int num_inputs) +draw_llvm_create_variant(struct draw_llvm *llvm, int num_inputs) { struct draw_llvm_variant *variant = MALLOC(sizeof(struct draw_llvm_variant)); + struct llvm_vertex_shader *shader = + llvm_vertex_shader(llvm->draw->vs.vertex_shader); + + variant->llvm = llvm; draw_llvm_make_variant_key(llvm, &variant->key); @@ -242,6 +276,12 @@ draw_llvm_prepare(struct draw_llvm *llvm, int num_inputs) draw_llvm_generate(llvm, variant); draw_llvm_generate_elts(llvm, variant); + variant->shader = shader; + variant->list_item_global.base = variant; + variant->list_item_local.base = variant; + /*variant->no = */shader->variants_created++; + variant->list_item_global.base = variant; + return variant; } @@ -897,3 +937,30 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm, &llvm->draw->vs.vertex_shader->state, sizeof(struct pipe_shader_state)); } + +void +draw_llvm_destroy_variant(struct draw_llvm_variant *variant) +{ + struct draw_llvm *llvm = variant->llvm; + struct draw_context *draw = llvm->draw; + + if (variant->function_elts) { + if (variant->function_elts) + LLVMFreeMachineCodeForFunction(draw->engine, + variant->function_elts); + LLVMDeleteFunction(variant->function_elts); + } + + if (variant->function) { + if (variant->function) + LLVMFreeMachineCodeForFunction(draw->engine, + variant->function); + LLVMDeleteFunction(variant->function); + } + + remove_from_list(&variant->list_item_local); + variant->shader->variants_cached--; + remove_from_list(&variant->list_item_global); + llvm->nr_variants--; + FREE(variant); +} -- 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/draw/draw_llvm.c') 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 ca88683459016d2cdc82175c718ee429e9440cf0 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Tue, 6 Jul 2010 12:35:23 -0400 Subject: draw: make sure softpipe doesn't crash with vertex tex sampling softpipe doesn't implement the draw's llvm tex sampling interface so make sure draw can handle the cases where the driver doesn't implement the interface --- src/gallium/auxiliary/draw/draw_llvm.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_llvm.c') diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 42653d36ec..facdafcc01 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -307,11 +307,12 @@ generate_vs(struct draw_llvm *llvm, LLVMValueRef (*outputs)[NUM_CHANNELS], const LLVMValueRef (*inputs)[NUM_CHANNELS], LLVMValueRef context_ptr, - struct lp_build_sampler_soa *sampler) + struct lp_build_sampler_soa *draw_sampler) { const struct tgsi_token *tokens = llvm->draw->vs.vertex_shader->state.tokens; struct lp_type vs_type; LLVMValueRef consts_ptr = draw_jit_context_vs_constants(builder, context_ptr); + struct lp_build_sampler_soa *sampler = 0; memset(&vs_type, 0, sizeof vs_type); vs_type.floating = TRUE; /* floating point values */ @@ -327,6 +328,10 @@ generate_vs(struct draw_llvm *llvm, tgsi_dump(tokens, 0); } + if (llvm->draw->num_sampler_views && + llvm->draw->num_samplers) + sampler = draw_sampler; + lp_build_tgsi_soa(builder, tokens, vs_type, @@ -972,12 +977,16 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm, &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]); + /* if the driver implemented the sampling hooks then + * setup our sampling state */ + if (llvm->draw->num_sampler_views && llvm->draw->num_samplers) { + 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]); + } } } -- cgit v1.2.3 From f8f1c629d6b2f86e65c5c0997b140cf8db8f616e Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Thu, 8 Jul 2010 17:54:47 -0700 Subject: draw: Fix off-by-one error in assert. textures is an array of size PIPE_MAX_VERTEX_SAMPLERS. --- src/gallium/auxiliary/draw/draw_llvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gallium/auxiliary/draw/draw_llvm.c') diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index facdafcc01..315544d7b8 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -1002,7 +1002,7 @@ draw_llvm_set_mapped_texture(struct draw_context *draw, unsigned j; struct draw_jit_texture *jit_tex; - assert(sampler_idx <= PIPE_MAX_VERTEX_SAMPLERS); + assert(sampler_idx < PIPE_MAX_VERTEX_SAMPLERS); jit_tex = &draw->llvm->jit_context.textures[sampler_idx]; -- cgit v1.2.3 From b77f5024ca2926404d701276eafc72f5769daa32 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 16 Jul 2010 11:58:20 -0400 Subject: draw: use the instance id when fetching vertex data --- src/gallium/auxiliary/draw/draw_llvm.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_llvm.c') diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 315544d7b8..61c53a06b3 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -368,7 +368,8 @@ generate_fetch(LLVMBuilderRef builder, LLVMValueRef *res, struct pipe_vertex_element *velem, LLVMValueRef vbuf, - LLVMValueRef index) + LLVMValueRef index, + unsigned instance_id) { LLVMValueRef indices = LLVMConstInt(LLVMInt64Type(), velem->vertex_buffer_index, 0); LLVMValueRef vbuffer_ptr = LLVMBuildGEP(builder, vbuffers_ptr, @@ -393,6 +394,11 @@ generate_fetch(LLVMBuilderRef builder, stride = LLVMBuildAdd(builder, stride, LLVMConstInt(LLVMInt32Type(), velem->src_offset, 0), ""); + if (velem->instance_divisor) { + stride = LLVMBuildMul(builder, stride, + LLVMConstInt(LLVMInt32Type(), instance_id, 0), + ""); + } /*lp_build_printf(builder, "vbuf index = %d, stride is %d\n", indices, stride);*/ vbuffer_ptr = LLVMBuildGEP(builder, vbuffer_ptr, &stride, 1, ""); @@ -745,7 +751,8 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) LLVMValueRef vb = LLVMBuildGEP(builder, vb_ptr, &vb_index, 1, ""); generate_fetch(builder, vbuffers_ptr, - &aos_attribs[j][i], velem, vb, true_index); + &aos_attribs[j][i], velem, vb, true_index, + draw->instance_id); } } convert_to_soa(builder, aos_attribs, inputs, @@ -908,7 +915,8 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian LLVMValueRef vb = LLVMBuildGEP(builder, vb_ptr, &vb_index, 1, ""); generate_fetch(builder, vbuffers_ptr, - &aos_attribs[j][i], velem, vb, true_index); + &aos_attribs[j][i], velem, vb, true_index, + draw->instance_id); } } convert_to_soa(builder, aos_attribs, inputs, -- cgit v1.2.3 From fab4ac9e942465cb184a74b3abc57c2e5353c5bf Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 16 Jul 2010 12:19:26 -0400 Subject: draw/llvm: adjust the instance id at run time fixes instancing in draw llvm --- src/gallium/auxiliary/draw/draw_llvm.c | 33 ++++++++++++++-------- src/gallium/auxiliary/draw/draw_llvm.h | 6 ++-- .../draw/draw_pt_fetch_shade_pipeline_llvm.c | 6 ++-- 3 files changed, 29 insertions(+), 16 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_llvm.c') diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 61c53a06b3..6958c3057c 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -369,7 +369,7 @@ generate_fetch(LLVMBuilderRef builder, struct pipe_vertex_element *velem, LLVMValueRef vbuf, LLVMValueRef index, - unsigned instance_id) + LLVMValueRef instance_id) { LLVMValueRef indices = LLVMConstInt(LLVMInt64Type(), velem->vertex_buffer_index, 0); LLVMValueRef vbuffer_ptr = LLVMBuildGEP(builder, vbuffers_ptr, @@ -382,6 +382,10 @@ generate_fetch(LLVMBuilderRef builder, cond = LLVMBuildICmp(builder, LLVMIntULE, index, vb_max_index, ""); + if (velem->instance_divisor) { + index = instance_id; + } + index = LLVMBuildSelect(builder, cond, index, vb_max_index, ""); stride = LLVMBuildMul(builder, vb_stride, index, ""); @@ -394,11 +398,6 @@ generate_fetch(LLVMBuilderRef builder, stride = LLVMBuildAdd(builder, stride, LLVMConstInt(LLVMInt32Type(), velem->src_offset, 0), ""); - if (velem->instance_divisor) { - stride = LLVMBuildMul(builder, stride, - LLVMConstInt(LLVMInt32Type(), instance_id, 0), - ""); - } /*lp_build_printf(builder, "vbuf index = %d, stride is %d\n", indices, stride);*/ vbuffer_ptr = LLVMBuildGEP(builder, vbuffer_ptr, &stride, 1, ""); @@ -654,13 +653,14 @@ convert_to_aos(LLVMBuilderRef builder, static void draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) { - LLVMTypeRef arg_types[7]; + LLVMTypeRef arg_types[8]; LLVMTypeRef func_type; LLVMValueRef context_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; LLVMValueRef start, end, count, stride, step, io_itr; LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr; + LLVMValueRef instance_id; struct draw_context *draw = llvm->draw; unsigned i, j; struct lp_build_context bld; @@ -678,6 +678,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) arg_types[4] = LLVMInt32Type(); /* count */ arg_types[5] = LLVMInt32Type(); /* stride */ arg_types[6] = llvm->vb_ptr_type; /* pipe_vertex_buffer's */ + arg_types[7] = LLVMInt32Type(); /* instance_id */ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); @@ -694,6 +695,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) count = LLVMGetParam(variant->function, 4); stride = LLVMGetParam(variant->function, 5); vb_ptr = LLVMGetParam(variant->function, 6); + instance_id = LLVMGetParam(variant->function, 7); lp_build_name(context_ptr, "context"); lp_build_name(io_ptr, "io"); @@ -702,6 +704,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) lp_build_name(count, "count"); lp_build_name(stride, "stride"); lp_build_name(vb_ptr, "vb"); + lp_build_name(instance_id, "instance_id"); /* * Function body @@ -752,7 +755,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) &vb_index, 1, ""); generate_fetch(builder, vbuffers_ptr, &aos_attribs[j][i], velem, vb, true_index, - draw->instance_id); + instance_id); } } convert_to_soa(builder, aos_attribs, inputs, @@ -807,13 +810,14 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) static void draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *variant) { - LLVMTypeRef arg_types[7]; + LLVMTypeRef arg_types[8]; LLVMTypeRef func_type; LLVMValueRef context_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; LLVMValueRef fetch_elts, fetch_count, stride, step, io_itr; LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr; + LLVMValueRef instance_id; struct draw_context *draw = llvm->draw; unsigned i, j; struct lp_build_context bld; @@ -833,14 +837,17 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian arg_types[4] = LLVMInt32Type(); /* fetch_count */ arg_types[5] = LLVMInt32Type(); /* stride */ arg_types[6] = llvm->vb_ptr_type; /* pipe_vertex_buffer's */ + arg_types[7] = LLVMInt32Type(); /* instance_id */ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); - variant->function_elts = LLVMAddFunction(llvm->module, "draw_llvm_shader_elts", func_type); + variant->function_elts = LLVMAddFunction(llvm->module, "draw_llvm_shader_elts", + func_type); LLVMSetFunctionCallConv(variant->function_elts, LLVMCCallConv); for(i = 0; i < Elements(arg_types); ++i) if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) - LLVMAddAttribute(LLVMGetParam(variant->function_elts, i), LLVMNoAliasAttribute); + LLVMAddAttribute(LLVMGetParam(variant->function_elts, i), + LLVMNoAliasAttribute); context_ptr = LLVMGetParam(variant->function_elts, 0); io_ptr = LLVMGetParam(variant->function_elts, 1); @@ -849,6 +856,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian fetch_count = LLVMGetParam(variant->function_elts, 4); stride = LLVMGetParam(variant->function_elts, 5); vb_ptr = LLVMGetParam(variant->function_elts, 6); + instance_id = LLVMGetParam(variant->function_elts, 7); lp_build_name(context_ptr, "context"); lp_build_name(io_ptr, "io"); @@ -857,6 +865,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian lp_build_name(fetch_count, "fetch_count"); lp_build_name(stride, "stride"); lp_build_name(vb_ptr, "vb"); + lp_build_name(instance_id, "instance_id"); /* * Function body @@ -916,7 +925,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian &vb_index, 1, ""); generate_fetch(builder, vbuffers_ptr, &aos_attribs[j][i], velem, vb, true_index, - draw->instance_id); + instance_id); } } convert_to_soa(builder, aos_attribs, inputs, diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h index 05446517c6..4addb47d2d 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.h +++ b/src/gallium/auxiliary/draw/draw_llvm.h @@ -135,7 +135,8 @@ typedef void unsigned start, unsigned count, unsigned stride, - struct pipe_vertex_buffer *vertex_buffers); + struct pipe_vertex_buffer *vertex_buffers, + unsigned instance_id); typedef void @@ -145,7 +146,8 @@ typedef void const unsigned *fetch_elts, unsigned fetch_count, unsigned stride, - struct pipe_vertex_buffer *vertex_buffers); + struct pipe_vertex_buffer *vertex_buffers, + unsigned instance_id); struct draw_llvm_variant_key { 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 6aefbede59..bc074df8c2 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 @@ -233,7 +233,8 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle, fetch_info->start, fetch_info->count, fpme->vertex_size, - draw->pt.vertex_buffer ); + draw->pt.vertex_buffer, + draw->instance_id); else fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context, llvm_vert_info.verts, @@ -241,7 +242,8 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle, fetch_info->elts, fetch_info->count, fpme->vertex_size, - draw->pt.vertex_buffer); + draw->pt.vertex_buffer, + draw->instance_id); /* Finished with fetch and vs: */ -- cgit v1.2.3 From 37692e5dc9bbcf4f48b4401255d47f724a602978 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 19 Jul 2010 18:29:12 -0600 Subject: draw: fix incorrect instancing divisor in LLVM code --- src/gallium/auxiliary/draw/draw_llvm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_llvm.c') diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 6958c3057c..1ee87697b4 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -380,12 +380,15 @@ generate_fetch(LLVMBuilderRef builder, LLVMValueRef cond; LLVMValueRef stride; - cond = LLVMBuildICmp(builder, LLVMIntULE, index, vb_max_index, ""); - if (velem->instance_divisor) { - index = instance_id; + /* array index = instance_id / instance_divisor */ + index = LLVMBuildUDiv(builder, instance_id, + LLVMConstInt(LLVMInt32Type(), velem->instance_divisor, 0), + "instance_divisor"); } + /* limit index to min(inex, vb_max_index) */ + cond = LLVMBuildICmp(builder, LLVMIntULE, index, vb_max_index, ""); index = LLVMBuildSelect(builder, cond, index, vb_max_index, ""); stride = LLVMBuildMul(builder, vb_stride, index, ""); -- cgit v1.2.3 From 815e79e72c1f4aa849c0ee6103621685b678bc9d Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 22 Jul 2010 16:07:18 -0600 Subject: draw: re-order optimization passes depending on LLVM version, 32/64-bit This is a work-around for an apparent bug in LLVM seen with piglit's glsl-vs-sqrt-zero test. --- src/gallium/auxiliary/draw/draw_llvm.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/gallium/auxiliary/draw/draw_llvm.c') diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 1ee87697b4..19f96c37ab 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -238,9 +238,22 @@ draw_llvm_create(struct draw_context *draw) /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, * but there are more on SVN. */ /* TODO: Add more passes */ + LLVMAddCFGSimplificationPass(llvm->pass); - LLVMAddPromoteMemoryToRegisterPass(llvm->pass); - LLVMAddConstantPropagationPass(llvm->pass); + + if (HAVE_LLVM >= 0x207 && sizeof(void*) == 4) { + /* For LLVM >= 2.7 and 32-bit build, use this order of passes to + * avoid generating bad code. + * Test with piglit glsl-vs-sqrt-zero test. + */ + LLVMAddConstantPropagationPass(llvm->pass); + LLVMAddPromoteMemoryToRegisterPass(llvm->pass); + } + else { + LLVMAddPromoteMemoryToRegisterPass(llvm->pass); + LLVMAddConstantPropagationPass(llvm->pass); + } + if(util_cpu_caps.has_sse4_1) { /* FIXME: There is a bug in this pass, whereby the combination of fptosi * and sitofp (necessary for trunc/floor/ceil/round implementation) -- cgit v1.2.3