summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary/draw
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary/draw')
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c57
-rw-r--r--src/gallium/auxiliary/draw/draw_context.h24
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c229
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.h145
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm_sample.c215
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm_translate.c4
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe.c52
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_aaline.c10
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_clip.c11
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_pstipple.c15
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_wide_point.c1
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h11
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c72
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h6
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch.c44
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c9
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c8
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c17
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c103
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_post_vs.c35
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray.c19
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache.c124
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.c5
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.h6
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_llvm.c120
25 files changed, 1057 insertions, 285 deletions
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index dab95e5051..c127f74188 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 );
}
@@ -211,6 +216,7 @@ void draw_set_clip_state( struct draw_context *draw,
assert(clip->nr <= PIPE_MAX_CLIP_PLANES);
memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0]));
draw->nr_planes = 6 + clip->nr;
+ draw->depth_clamp = clip->depth_clamp;
}
@@ -601,3 +607,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..116716af6f 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -47,11 +47,14 @@ 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 );
void draw_destroy( struct draw_context *draw );
+void draw_flush(struct draw_context *draw);
+
void draw_set_viewport_state( struct draw_context *draw,
const struct pipe_viewport_state *viewport );
@@ -101,6 +104,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]);
/*
@@ -173,7 +193,7 @@ draw_set_so_state(struct draw_context *draw,
/***********************************************************************
- * draw_prim.c
+ * draw_pt.c
*/
void draw_arrays(struct draw_context *draw, unsigned prim,
@@ -187,8 +207,6 @@ draw_arrays_instanced(struct draw_context *draw,
unsigned startInstance,
unsigned instanceCount);
-void draw_flush(struct draw_context *draw);
-
/*******************************************************************************
* Driver backend interface
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index 9117c1303d..19f96c37ab 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"
@@ -15,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 <llvm-c/Transforms/Scalar.h>
#define DEBUG_STORE 0
-
/* generates the draw jit function */
static void
draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *var);
@@ -36,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);
@@ -51,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);
@@ -71,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);
@@ -81,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);
@@ -195,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)
@@ -219,6 +275,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 +290,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 +305,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;
}
@@ -250,11 +319,13 @@ 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 *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 */
@@ -270,6 +341,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,
@@ -278,7 +353,7 @@ generate_vs(struct draw_llvm *llvm,
NULL /*pos*/,
inputs,
outputs,
- NULL/*sampler*/,
+ sampler,
&llvm->draw->vs.vertex_shader->info);
}
@@ -306,7 +381,8 @@ generate_fetch(LLVMBuilderRef builder,
LLVMValueRef *res,
struct pipe_vertex_element *velem,
LLVMValueRef vbuf,
- LLVMValueRef index)
+ LLVMValueRef index,
+ LLVMValueRef instance_id)
{
LLVMValueRef indices = LLVMConstInt(LLVMInt64Type(), velem->vertex_buffer_index, 0);
LLVMValueRef vbuffer_ptr = LLVMBuildGEP(builder, vbuffers_ptr,
@@ -317,8 +393,15 @@ generate_fetch(LLVMBuilderRef builder,
LLVMValueRef cond;
LLVMValueRef stride;
- cond = LLVMBuildICmp(builder, LLVMIntULE, index, vb_max_index, "");
+ if (velem->instance_divisor) {
+ /* 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, "");
@@ -586,13 +669,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;
@@ -601,6 +685,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 */
@@ -609,6 +694,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);
@@ -625,6 +711,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");
@@ -633,6 +720,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
@@ -648,6 +736,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);
@@ -678,7 +770,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,
+ instance_id);
}
}
convert_to_soa(builder, aos_attribs, inputs,
@@ -689,7 +782,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,
@@ -697,6 +791,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);
@@ -730,13 +826,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;
@@ -747,6 +844,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 */
@@ -755,14 +853,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);
@@ -771,6 +872,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");
@@ -779,6 +881,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
@@ -793,6 +896,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");
@@ -833,7 +940,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,
+ instance_id);
}
}
convert_to_soa(builder, aos_attribs, inputs,
@@ -844,7 +952,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,
@@ -852,6 +961,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);
@@ -885,6 +996,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;
@@ -896,4 +1009,72 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm,
memcpy(&key->vs,
&llvm->draw->vs.vertex_shader->state,
sizeof(struct pipe_shader_state));
+
+ /* 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]);
+ }
+ }
+}
+
+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
+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);
}
diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h
index 58fee7f9d6..4addb47d2d 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.h
+++ b/src/gallium/auxiliary/draw/draw_llvm.h
@@ -1,28 +1,71 @@
-#ifndef HAVE_LLVM_H
-#define HAVE_LLVM_H
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#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"
#include <llvm-c/Core.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/Target.h>
#include <llvm-c/ExecutionEngine.h>
+#define DRAW_MAX_TEXTURE_LEVELS 13 /* 4K x 4K for now */
+
+struct draw_llvm;
+struct llvm_vertex_shader;
+
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 {
@@ -48,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];
};
@@ -58,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")
@@ -92,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
@@ -102,13 +146,54 @@ 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
+{
+ 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
+{
+ struct draw_llvm_variant *base;
+ struct draw_llvm_variant_list_item *next, *prev;
+};
+
+struct draw_llvm_variant
+{
+ struct draw_llvm_variant_key key;
+ LLVMValueRef function;
+ LLVMValueRef function_elts;
+ draw_jit_vert_func jit_func;
+ draw_jit_vert_func_elts jit_func_elts;
+
+ struct llvm_vertex_shader *shader;
+
+ struct draw_llvm *llvm;
+ struct draw_llvm_variant_list_item list_item_global;
+ struct draw_llvm_variant_list_item list_item_local;
+};
+
+struct llvm_vertex_shader {
+ struct draw_vertex_shader base;
+
+ struct draw_llvm_variant_list_item variants;
+ unsigned variants_created;
+ unsigned variants_cached;
+};
struct draw_llvm {
struct draw_context *draw;
struct draw_jit_context jit_context;
+ struct draw_llvm_variant_list_item vs_variants_list;
+ int nr_variants;
+
LLVMModuleRef module;
LLVMExecutionEngineRef engine;
LLVMModuleProviderRef provider;
@@ -121,23 +206,12 @@ struct draw_llvm {
LLVMTypeRef vb_ptr_type;
};
-struct draw_llvm_variant_key
+static INLINE struct llvm_vertex_shader *
+llvm_vertex_shader(struct draw_vertex_shader *vs)
{
- struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
- unsigned nr_vertex_elements;
- struct pipe_shader_state vs;
-};
+ return (struct llvm_vertex_shader *)vs;
+}
-struct draw_llvm_variant
-{
- struct draw_llvm_variant_key key;
- LLVMValueRef function;
- LLVMValueRef function_elts;
- draw_jit_vert_func jit_func;
- draw_jit_vert_func_elts jit_func_elts;
-
- struct draw_llvm_variant *next;
-};
struct draw_llvm *
draw_llvm_create(struct draw_context *draw);
@@ -146,7 +220,10 @@ void
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);
+
+void
+draw_llvm_destroy_variant(struct draw_llvm_variant *variant);
void
draw_llvm_make_variant_key(struct draw_llvm *llvm,
@@ -156,4 +233,18 @@ LLVMValueRef
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..e9811010db
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_llvm_sample.c
@@ -0,0 +1,215 @@
+/**************************************************************************
+ *
+ * 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 <jfonseca@vmware.com>
+ */
+
+#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_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_llvm_translate.c b/src/gallium/auxiliary/draw/draw_llvm_translate.c
index d7da7ed357..6ebe1f7de4 100644
--- a/src/gallium/auxiliary/draw/draw_llvm_translate.c
+++ b/src/gallium/auxiliary/draw/draw_llvm_translate.c
@@ -7,6 +7,7 @@
#include "gallivm/lp_bld_struct.h"
#include "gallivm/lp_bld_format.h"
#include "gallivm/lp_bld_debug.h"
+#include "gallivm/lp_bld_type.h"
#include "util/u_memory.h"
#include "util/u_format.h"
@@ -466,6 +467,7 @@ draw_llvm_translate_from(LLVMBuilderRef builder,
const struct util_format_description *format_desc;
LLVMValueRef zero;
int i;
+ struct lp_type type = lp_float32_vec4_type();
/*
* The above can only cope with straight arrays: no bitfields,
@@ -493,5 +495,5 @@ draw_llvm_translate_from(LLVMBuilderRef builder,
format_desc = util_format_description(from_format);
zero = LLVMConstNull(LLVMInt32Type());
- return lp_build_fetch_rgba_aos(builder, format_desc, vbuffer, zero, zero);
+ return lp_build_fetch_rgba_aos(builder, format_desc, type, vbuffer, zero, zero, zero);
}
diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c
index 83556f10a8..8cd75ecf9a 100644
--- a/src/gallium/auxiliary/draw/draw_pipe.c
+++ b/src/gallium/auxiliary/draw/draw_pipe.c
@@ -177,15 +177,15 @@ static void do_triangle( struct draw_context *draw,
( DRAW_PIPE_RESET_STIPPLE | \
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
- verts + stride * elts[i0], \
- verts + stride * elts[i1], \
- verts + stride * elts[i2]); \
+ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_1 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
- verts + stride * elts[i0], \
- verts + stride * elts[i2], \
- verts + stride * elts[i3])
+ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK))
/* emit last quad vertex as last vertex in triangles */
#define QUAD_LAST_PV(i0,i1,i2,i3) \
@@ -193,15 +193,15 @@ static void do_triangle( struct draw_context *draw,
( DRAW_PIPE_RESET_STIPPLE | \
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
- verts + stride * elts[i0], \
- verts + stride * elts[i1], \
- verts + stride * elts[i3]); \
+ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
- verts + stride * elts[i1], \
- verts + stride * elts[i2], \
- verts + stride * elts[i3])
+ verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK))
#define TRIANGLE(flags,i0,i1,i2) \
do_triangle( draw, \
@@ -218,7 +218,7 @@ static void do_triangle( struct draw_context *draw,
#define POINT(i0) \
do_point( draw, \
- verts + stride * elts[i0] )
+ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK) )
#define FUNC pipe_run
#define ARGS \
@@ -260,7 +260,7 @@ void draw_pipeline_run( struct draw_context *draw,
const struct draw_prim_info *prim_info)
{
unsigned i, start;
-
+
draw->pipeline.verts = (char *)vert_info->verts;
draw->pipeline.vertex_stride = vert_info->stride;
draw->pipeline.vertex_count = vert_info->count;
@@ -296,14 +296,14 @@ void draw_pipeline_run( struct draw_context *draw,
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i1), \
- verts + stride * (i2)); \
+ verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_1 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i2), \
- verts + stride * (i3))
+ verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK))
/* emit last quad vertex as last vertex in triangles */
#define QUAD_LAST_PV(i0,i1,i2,i3) \
@@ -312,31 +312,31 @@ void draw_pipeline_run( struct draw_context *draw,
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i1), \
- verts + stride * (i3)); \
+ verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i2), \
- verts + stride * (i3))
+ verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK))
#define TRIANGLE(flags,i0,i1,i2) \
do_triangle( draw, \
flags, /* flags */ \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i1), \
- verts + stride * (i2))
+ verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK))
#define LINE(flags,i0,i1) \
do_line( draw, \
flags, \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i1))
+ verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK))
#define POINT(i0) \
do_point( draw, \
- verts + stride * i0 )
+ verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK) )
#define FUNC pipe_run_linear
#define ARGS \
diff --git a/src/gallium/auxiliary/draw/draw_pipe_aaline.c b/src/gallium/auxiliary/draw/draw_pipe_aaline.c
index debd17fd74..c0135f5bb7 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_aaline.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_aaline.c
@@ -425,7 +425,8 @@ aaline_create_texture(struct aaline_stage *aaline)
/* Fill in mipmap images.
* Basically each level is solid opaque, except for the outermost
- * texels which are zero. Special case the 1x1 and 2x2 levels.
+ * texels which are zero. Special case the 1x1 and 2x2 levels
+ * (though, those levels shouldn't be used - see the max_lod setting).
*/
for (level = 0; level <= MAX_TEXTURE_LEVEL; level++) {
struct pipe_transfer *transfer;
@@ -497,7 +498,8 @@ aaline_create_sampler(struct aaline_stage *aaline)
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.normalized_coords = 1;
sampler.min_lod = 0.0f;
- sampler.max_lod = MAX_TEXTURE_LEVEL;
+ /* avoid using the 1x1 and 2x2 mipmap levels */
+ sampler.max_lod = MAX_TEXTURE_LEVEL - 2;
aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
if (aaline->sampler_cso == NULL)
@@ -669,8 +671,8 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header)
assert(draw->rasterizer->line_smooth);
- if (draw->rasterizer->line_width <= 3.0)
- aaline->half_line_width = 1.5f;
+ if (draw->rasterizer->line_width <= 2.2)
+ aaline->half_line_width = 1.1f;
else
aaline->half_line_width = 0.5f * draw->rasterizer->line_width;
diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c
index 122b1c7968..1cf6ee7a7f 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_clip.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c
@@ -262,6 +262,7 @@ do_clip_tri( struct draw_stage *stage,
clipmask &= ~(1<<plane_idx);
+ assert(n < MAX_CLIPPED_VERTICES);
inlist[n] = inlist[0]; /* prevent rotation of vertices */
for (i = 1; i <= n; i++) {
@@ -270,11 +271,17 @@ do_clip_tri( struct draw_stage *stage,
float dp = dot4( vert->clip, plane );
if (!IS_NEGATIVE(dp_prev)) {
+ assert(outcount < MAX_CLIPPED_VERTICES);
outlist[outcount++] = vert_prev;
}
if (DIFFERENT_SIGNS(dp, dp_prev)) {
- struct vertex_header *new_vert = clipper->stage.tmp[tmpnr++];
+ struct vertex_header *new_vert;
+
+ assert(tmpnr < MAX_CLIPPED_VERTICES+1);
+ new_vert = clipper->stage.tmp[tmpnr++];
+
+ assert(outcount < MAX_CLIPPED_VERTICES);
outlist[outcount++] = new_vert;
if (IS_NEGATIVE(dp)) {
@@ -317,12 +324,14 @@ do_clip_tri( struct draw_stage *stage,
if (clipper->flat) {
if (stage->draw->rasterizer->flatshade_first) {
if (inlist[0] != header->v[0]) {
+ assert(tmpnr < MAX_CLIPPED_VERTICES + 1);
inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
copy_colors(stage, inlist[0], header->v[0]);
}
}
else {
if (inlist[0] != header->v[2]) {
+ assert(tmpnr < MAX_CLIPPED_VERTICES + 1);
inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
copy_colors(stage, inlist[0], header->v[2]);
}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
index fff960c7eb..ed9a53e154 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
@@ -363,8 +363,12 @@ generate_pstip_fs(struct pstip_stage *pstip)
assert(pstip->fs->sampler_unit < PIPE_MAX_SAMPLERS);
pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs);
-
+
FREE((void *)pstip_fs.tokens);
+
+ if (!pstip->fs->pstip_fs)
+ return FALSE;
+
return TRUE;
}
@@ -603,13 +607,16 @@ pstip_destroy(struct draw_stage *stage)
}
+/** Create a new polygon stipple drawing stage object */
static struct pstip_stage *
-draw_pstip_stage(struct draw_context *draw)
+draw_pstip_stage(struct draw_context *draw, struct pipe_context *pipe)
{
struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage);
if (pstip == NULL)
goto fail;
+ pstip->pipe = pipe;
+
pstip->stage.draw = draw;
pstip->stage.name = "pstip";
pstip->stage.next = NULL;
@@ -765,14 +772,12 @@ draw_install_pstipple_stage(struct draw_context *draw,
/*
* Create / install pgon stipple drawing / prim stage
*/
- pstip = draw_pstip_stage( draw );
+ pstip = draw_pstip_stage( draw, pipe );
if (pstip == NULL)
goto fail;
draw->pipeline.pstipple = &pstip->stage;
- pstip->pipe = pipe;
-
/* create special texture, sampler state */
if (!pstip_create_texture(pstip))
goto fail;
diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c
index 3e6e538995..ee2945c7c9 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c
@@ -226,6 +226,7 @@ static void widepoint_first_point( struct draw_stage *stage,
if (rast->gl_rasterization_rules) {
wide->xbias = 0.125;
+ wide->ybias = -0.125;
}
/* Disable triangle culling, stippling, unfilled mode etc. */
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 4584033bc2..058aeedc17 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 <llvm-c/ExecutionEngine.h>
+struct draw_llvm;
#endif
@@ -81,6 +82,9 @@ struct vertex_header {
#define UNDEFINED_VERTEX_ID 0xffff
+/* maximum number of shader variants we can cache */
+#define DRAW_MAX_SHADER_VARIANTS 1024
+
/**
* Private context for the drawing module.
*/
@@ -245,6 +249,7 @@ struct draw_context
*/
float plane[12][4];
unsigned nr_planes;
+ boolean depth_clamp;
/* If a prim stage introduces new vertex attributes, they'll be stored here
*/
@@ -259,9 +264,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.c b/src/gallium/auxiliary/draw/draw_pt.c
index 02c97fec81..92d4113b4c 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -34,9 +34,11 @@
#include "draw/draw_gs.h"
#include "draw/draw_private.h"
#include "draw/draw_pt.h"
+#include "draw/draw_vs.h"
#include "tgsi/tgsi_dump.h"
#include "util/u_math.h"
#include "util/u_prim.h"
+#include "util/u_format.h"
DEBUG_GET_ONCE_BOOL_OPTION(draw_fse, "DRAW_FSE", FALSE)
@@ -69,7 +71,6 @@ draw_pt_arrays(struct draw_context *draw,
struct draw_pt_front_end *frontend = NULL;
struct draw_pt_middle_end *middle = NULL;
unsigned opt = 0;
- unsigned out_prim = prim;
/* Sanitize primitive length:
*/
@@ -80,18 +81,19 @@ draw_pt_arrays(struct draw_context *draw,
if (count < first)
return TRUE;
}
- if (draw->gs.geometry_shader) {
- out_prim = draw->gs.geometry_shader->output_primitive;
- }
if (!draw->force_passthrough) {
+ unsigned gs_out_prim = (draw->gs.geometry_shader ?
+ draw->gs.geometry_shader->output_primitive :
+ prim);
+
if (!draw->render) {
opt |= PT_PIPELINE;
}
if (draw_need_pipeline(draw,
draw->rasterizer,
- out_prim)) {
+ gs_out_prim)) {
opt |= PT_PIPELINE;
}
@@ -102,7 +104,7 @@ draw_pt_arrays(struct draw_context *draw,
opt |= PT_SHADE;
}
- if (draw->pt.middle.llvm && !draw->gs.geometry_shader) {
+ if (draw->pt.middle.llvm) {
middle = draw->pt.middle.llvm;
} else {
if (opt == 0)
@@ -122,7 +124,7 @@ draw_pt_arrays(struct draw_context *draw,
frontend = draw->pt.front.varray;
}
- frontend->prepare( frontend, prim, out_prim, middle, opt );
+ frontend->prepare( frontend, prim, middle, opt );
frontend->run(frontend,
draw_pt_elt_func(draw),
@@ -265,31 +267,38 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
case PIPE_FORMAT_R32_FLOAT:
{
float *v = (float *) ptr;
- debug_printf("%f @ %p\n", v[0], (void *) v);
+ debug_printf("R %f @ %p\n", v[0], (void *) v);
}
break;
case PIPE_FORMAT_R32G32_FLOAT:
{
float *v = (float *) ptr;
- debug_printf("%f %f @ %p\n", v[0], v[1], (void *) v);
+ debug_printf("RG %f %f @ %p\n", v[0], v[1], (void *) v);
}
break;
case PIPE_FORMAT_R32G32B32_FLOAT:
{
float *v = (float *) ptr;
- debug_printf("%f %f %f @ %p\n", v[0], v[1], v[2], (void *) v);
+ debug_printf("RGB %f %f %f @ %p\n", v[0], v[1], v[2], (void *) v);
}
break;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
{
float *v = (float *) ptr;
- debug_printf("%f %f %f %f @ %p\n", v[0], v[1], v[2], v[3],
+ debug_printf("RGBA %f %f %f %f @ %p\n", v[0], v[1], v[2], v[3],
(void *) v);
}
break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ {
+ ubyte *u = (ubyte *) ptr;
+ debug_printf("BGRA %d %d %d %d @ %p\n", u[0], u[1], u[2], u[3],
+ (void *) u);
+ }
+ break;
default:
- debug_printf("other format (fix me)\n");
- ;
+ debug_printf("other format %s (fix me)\n",
+ util_format_name(draw->pt.vertex_element[j].src_format));
}
}
}
@@ -297,11 +306,8 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
/**
- * Draw vertex arrays
- * This is the main entrypoint into the drawing module.
- * \param prim one of PIPE_PRIM_x
- * \param start index of first vertex to draw
- * \param count number of vertices to draw
+ * Non-instanced drawing.
+ * \sa draw_arrays_instanced
*/
void
draw_arrays(struct draw_context *draw, unsigned prim,
@@ -310,6 +316,20 @@ draw_arrays(struct draw_context *draw, unsigned prim,
draw_arrays_instanced(draw, prim, start, count, 0, 1);
}
+
+/**
+ * Draw vertex arrays.
+ * This is the main entrypoint into the drawing module.
+ * If drawing an indexed primitive, the draw_set_mapped_element_buffer_range()
+ * function should have already been called to specify the element/index buffer
+ * information.
+ *
+ * \param prim one of PIPE_PRIM_x
+ * \param start index of first vertex to draw
+ * \param count number of vertices to draw
+ * \param startInstance number for the first primitive instance (usually 0).
+ * \param instanceCount number of instances to draw (1=non-instanced)
+ */
void
draw_arrays_instanced(struct draw_context *draw,
unsigned mode,
@@ -329,26 +349,30 @@ draw_arrays_instanced(struct draw_context *draw,
if (0)
draw_print_arrays(draw, mode, start, MIN2(count, 20));
-#if 0
- {
- int i;
+ if (0) {
+ unsigned int i;
debug_printf("draw_arrays(mode=%u start=%u count=%u):\n",
mode, start, count);
tgsi_dump(draw->vs.vertex_shader->state.tokens, 0);
debug_printf("Elements:\n");
for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
- debug_printf(" format=%s\n",
+ debug_printf(" %u: src_offset=%u inst_div=%u vbuf=%u format=%s\n",
+ i,
+ draw->pt.vertex_element[i].src_offset,
+ draw->pt.vertex_element[i].instance_divisor,
+ draw->pt.vertex_element[i].vertex_buffer_index,
util_format_name(draw->pt.vertex_element[i].src_format));
}
debug_printf("Buffers:\n");
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
- debug_printf(" stride=%u offset=%u ptr=%p\n",
+ debug_printf(" %u: stride=%u maxindex=%u offset=%u ptr=%p\n",
+ i,
draw->pt.vertex_buffer[i].stride,
+ draw->pt.vertex_buffer[i].max_index,
draw->pt.vertex_buffer[i].buffer_offset,
draw->pt.user.vbuffer[i]);
}
}
-#endif
for (instance = 0; instance < instanceCount; instance++) {
draw->instance_id = instance + startInstance;
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
index b6741ca83c..44356fba4c 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -62,8 +62,7 @@ struct draw_vertex_info;
*/
struct draw_pt_front_end {
void (*prepare)( struct draw_pt_front_end *,
- unsigned input_prim,
- unsigned output_prim,
+ unsigned prim,
struct draw_pt_middle_end *,
unsigned opt );
@@ -87,8 +86,7 @@ struct draw_pt_front_end {
*/
struct draw_pt_middle_end {
void (*prepare)( struct draw_pt_middle_end *,
- unsigned input_prim,
- unsigned output_prim,
+ unsigned prim,
unsigned opt,
unsigned *max_vertices );
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c
index bf799db352..ae12ee24bd 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c
@@ -68,31 +68,12 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
fetch->vertex_size = vertex_size;
- /* Always emit/leave space for a vertex header.
- *
- * It's worth considering whether the vertex headers should contain
- * a pointer to the 'data', rather than having it inline.
- * Something to look at after we've fully switched over to the pt
- * paths.
+ /* Leave the clipmask/edgeflags/pad/vertex_id untouched
*/
- {
- /* Need to set header->vertex_id = 0xffff somehow.
- */
- key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
- key.element[nr].input_format = PIPE_FORMAT_R32_FLOAT;
- key.element[nr].input_buffer = draw->pt.nr_vertex_buffers;
- key.element[nr].input_offset = 0;
- key.element[nr].instance_divisor = 0;
- key.element[nr].output_format = PIPE_FORMAT_R32_FLOAT;
- key.element[nr].output_offset = dst_offset;
- dst_offset += 1 * sizeof(float);
- nr++;
-
-
- /* Just leave the clip[] array untouched.
- */
- dst_offset += 4 * sizeof(float);
- }
+ dst_offset += 1 * sizeof(float);
+ /* Just leave the clip[] array untouched.
+ */
+ dst_offset += 4 * sizeof(float);
if (instance_id_index != ~0) {
num_extra_inputs++;
@@ -131,26 +112,11 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
key.nr_elements = nr;
key.output_stride = vertex_size;
-
if (!fetch->translate ||
translate_key_compare(&fetch->translate->key, &key) != 0)
{
translate_key_sanitize(&key);
fetch->translate = translate_cache_find(fetch->cache, &key);
-
- {
- static struct vertex_header vh = { 0,
- 1,
- 0,
- UNDEFINED_VERTEX_ID,
- { .0f, .0f, .0f, .0f } };
-
- fetch->translate->set_buffer(fetch->translate,
- draw->pt.nr_vertex_buffers,
- &vh,
- 0,
- ~0);
- }
}
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
index c629d55563..5c8af17c8e 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -36,6 +36,7 @@
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
+#include "draw/draw_gs.h"
#include "translate/translate.h"
#include "translate/translate_cache.h"
@@ -90,7 +91,6 @@ struct fetch_emit_middle_end {
static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
unsigned prim,
- unsigned out_prim,
unsigned opt,
unsigned *max_vertices )
{
@@ -101,9 +101,14 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
boolean ok;
struct translate_key key;
+ unsigned gs_out_prim = (draw->gs.geometry_shader ?
+ draw->gs.geometry_shader->output_primitive :
+ prim);
+
+
ok = draw->render->set_primitive( draw->render,
- out_prim );
+ gs_out_prim );
if (!ok) {
assert(0);
return;
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
index 5483a25f1d..b8270280b6 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
@@ -68,8 +68,7 @@ struct fetch_shade_emit {
static void fse_prepare( struct draw_pt_middle_end *middle,
- unsigned in_prim,
- unsigned out_prim,
+ unsigned prim,
unsigned opt,
unsigned *max_vertices )
{
@@ -80,9 +79,12 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
unsigned i;
unsigned nr_vbs = 0;
+ /* Can't support geometry shader on this path.
+ */
+ assert(!draw->gs.geometry_shader);
if (!draw->render->set_primitive( draw->render,
- out_prim )) {
+ prim )) {
assert(0);
return;
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
index 43b08a030c..121dfc414a 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -48,13 +48,11 @@ struct fetch_pipeline_middle_end {
unsigned vertex_data_offset;
unsigned vertex_size;
unsigned input_prim;
- unsigned output_prim;
unsigned opt;
};
static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
- unsigned in_prim,
- unsigned out_prim,
+ unsigned prim,
unsigned opt,
unsigned *max_vertices )
{
@@ -64,6 +62,10 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
unsigned i;
unsigned instance_id_index = ~0;
+ unsigned gs_out_prim = (draw->gs.geometry_shader ?
+ draw->gs.geometry_shader->output_primitive :
+ prim);
+
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
*/
@@ -79,8 +81,7 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
}
}
- fpme->input_prim = in_prim;
- fpme->output_prim = out_prim;
+ fpme->input_prim = prim;
fpme->opt = opt;
/* Always leave room for the vertex header whether we need it or
@@ -102,13 +103,13 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
(boolean)draw->bypass_clipping,
(boolean)draw->identity_viewport,
(boolean)draw->rasterizer->gl_rasterization_rules,
- (draw->vs.edgeflag_output ? true : false) );
+ (draw->vs.edgeflag_output ? TRUE : FALSE) );
draw_pt_so_emit_prepare( fpme->so_emit );
if (!(opt & PT_PIPELINE)) {
draw_pt_emit_prepare( fpme->emit,
- out_prim,
+ gs_out_prim,
max_vertices );
*max_vertices = MAX2( *max_vertices,
@@ -183,7 +184,7 @@ static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
output_verts->count = input_verts->count;
output_verts->verts =
(struct vertex_header *)MALLOC(output_verts->vertex_size *
- output_verts->count);
+ align(output_verts->count, 4));
vshader->run_linear(vshader,
(const float (*)[4])input_verts->verts->data,
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 7d2de58e73..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
@@ -49,48 +49,50 @@ struct llvm_middle_end {
unsigned vertex_data_offset;
unsigned vertex_size;
unsigned input_prim;
- unsigned output_prim;
unsigned opt;
struct draw_llvm *llvm;
- struct draw_llvm_variant *variants;
struct draw_llvm_variant *current_variant;
- int nr_variants;
};
static void
llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
unsigned in_prim,
- unsigned out_prim,
unsigned opt,
unsigned *max_vertices )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
struct draw_context *draw = fpme->draw;
- struct draw_vertex_shader *vs = draw->vs.vertex_shader;
+ struct llvm_vertex_shader *shader =
+ llvm_vertex_shader(draw->vs.vertex_shader);
struct draw_llvm_variant_key key;
struct draw_llvm_variant *variant = NULL;
+ struct draw_llvm_variant_list_item *li;
unsigned i;
unsigned instance_id_index = ~0;
+
+ unsigned out_prim = (draw->gs.geometry_shader ?
+ draw->gs.geometry_shader->output_primitive :
+ in_prim);
+
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
*/
- unsigned nr = MAX2( vs->info.num_inputs,
- vs->info.num_outputs + 1 );
+ unsigned nr = MAX2( shader->base.info.num_inputs,
+ shader->base.info.num_outputs + 1 );
/* Scan for instanceID system value.
*/
- for (i = 0; i < vs->info.num_inputs; i++) {
- if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
+ for (i = 0; i < shader->base.info.num_inputs; i++) {
+ if (shader->base.info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
instance_id_index = i;
break;
}
}
fpme->input_prim = in_prim;
- fpme->output_prim = out_prim;
fpme->opt = opt;
/* Always leave room for the vertex header whether we need it or
@@ -107,7 +109,7 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
(boolean)draw->bypass_clipping,
(boolean)(draw->identity_viewport),
(boolean)draw->rasterizer->gl_rasterization_rules,
- (draw->vs.edgeflag_output ? true : false) );
+ (draw->vs.edgeflag_output ? TRUE : FALSE) );
draw_pt_so_emit_prepare( fpme->so_emit );
@@ -128,20 +130,41 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
draw_llvm_make_variant_key(fpme->llvm, &key);
- variant = fpme->variants;
- while(variant) {
- if(memcmp(&variant->key, &key, sizeof key) == 0)
+ li = first_elem(&shader->variants);
+ while(!at_end(&shader->variants, li)) {
+ if(memcmp(&li->base->key, &key, sizeof key) == 0) {
+ variant = li->base;
break;
+ }
+ li = next_elem(li);
+ }
- variant = variant->next;
+ if (variant) {
+ move_to_head(&fpme->llvm->vs_variants_list, &variant->list_item_global);
}
+ else {
+ unsigned i;
+ if (fpme->llvm->nr_variants >= DRAW_MAX_SHADER_VARIANTS) {
+ /*
+ * XXX: should we flush here ?
+ */
+ for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 4; i++) {
+ struct draw_llvm_variant_list_item *item =
+ last_elem(&fpme->llvm->vs_variants_list);
+ draw_llvm_destroy_variant(item->base);
+ }
+ }
+
+ variant = draw_llvm_create_variant(fpme->llvm, nr);
- if (!variant) {
- variant = draw_llvm_prepare(fpme->llvm, nr);
- variant->next = fpme->variants;
- fpme->variants = variant;
- ++fpme->nr_variants;
+ if (variant) {
+ insert_at_head(&shader->variants, &variant->list_item_local);
+ insert_at_head(&fpme->llvm->vs_variants_list, &variant->list_item_global);
+ fpme->llvm->nr_variants++;
+ shader->variants_cached++;
+ }
}
+
fpme->current_variant = variant;
/*XXX we only support one constant buffer */
@@ -210,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,
@@ -218,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:
*/
@@ -356,31 +381,7 @@ static void llvm_middle_end_finish( struct draw_pt_middle_end *middle )
static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
- struct draw_context *draw = fpme->draw;
- struct draw_llvm_variant *variant = NULL;
-
- variant = fpme->variants;
- while(variant) {
- struct draw_llvm_variant *next = variant->next;
- 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);
- }
-
- FREE(variant);
-
- variant = next;
- }
if (fpme->fetch)
draw_pt_fetch_destroy( fpme->fetch );
@@ -393,14 +394,12 @@ 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);
}
-struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm( struct draw_context *draw )
+struct draw_pt_middle_end *
+draw_pt_fetch_pipeline_or_emit_llvm(struct draw_context *draw)
{
struct llvm_middle_end *fpme = 0;
@@ -436,13 +435,11 @@ struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm( struct draw_cont
if (!fpme->so_emit)
goto fail;
- fpme->llvm = draw_llvm_create(draw);
+ fpme->llvm = draw->llvm;
if (!fpme->llvm)
goto fail;
- fpme->variants = NULL;
fpme->current_variant = NULL;
- fpme->nr_variants = 0;
return &fpme->base;
diff --git a/src/gallium/auxiliary/draw/draw_pt_post_vs.c b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
index 112be50f9a..308f927b77 100644
--- a/src/gallium/auxiliary/draw/draw_pt_post_vs.c
+++ b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
@@ -38,7 +38,14 @@ struct pt_post_vs {
struct draw_vertex_info *info );
};
-
+static INLINE void
+initialize_vertex_header(struct vertex_header *header)
+{
+ header->clipmask = 0;
+ header->edgeflag = 1;
+ header->pad = 0;
+ header->vertex_id = UNDEFINED_VERTEX_ID;
+}
static INLINE float
dot4(const float *a, const float *b)
@@ -49,10 +56,9 @@ dot4(const float *a, const float *b)
a[3]*b[3]);
}
-
-
static INLINE unsigned
-compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr)
+compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr,
+ boolean clip_depth)
{
unsigned mask = 0x0;
unsigned i;
@@ -69,8 +75,10 @@ compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr)
if ( clip[0] + clip[3] < 0) mask |= (1<<1);
if (-clip[1] + clip[3] < 0) mask |= (1<<2);
if ( clip[1] + clip[3] < 0) mask |= (1<<3);
- if ( clip[2] + clip[3] < 0) mask |= (1<<4); /* match mesa clipplane numbering - for now */
- if (-clip[2] + clip[3] < 0) mask |= (1<<5); /* match mesa clipplane numbering - for now */
+ if (clip_depth) {
+ if ( clip[2] + clip[3] < 0) mask |= (1<<4); /* match mesa clipplane numbering - for now */
+ if (-clip[2] + clip[3] < 0) mask |= (1<<5); /* match mesa clipplane numbering - for now */
+ }
/* Followed by any remaining ones:
*/
@@ -103,6 +111,7 @@ static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
for (j = 0; j < info->count; j++) {
float *position = out->data[pos];
+ initialize_vertex_header(out);
#if 0
debug_printf("%d) io = %p, data = %p = [%f, %f, %f, %f]\n",
j, out, position, position[0], position[1], position[2], position[3]);
@@ -114,9 +123,11 @@ static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
out->clip[3] = position[3];
out->vertex_id = 0xffff;
+ /* Disable depth clipping if depth clamping is enabled. */
out->clipmask = compute_clipmask_gl(out->clip,
pvs->draw->plane,
- pvs->draw->nr_planes);
+ pvs->draw->nr_planes,
+ !pvs->draw->depth_clamp);
clipped += out->clipmask;
if (out->clipmask == 0)
@@ -192,6 +203,7 @@ static boolean post_vs_viewport( struct pt_post_vs *pvs,
for (j = 0; j < info->count; j++) {
float *position = out->data[pos];
+ initialize_vertex_header(out);
/* Viewport mapping only, no cliptest/rhw divide
*/
position[0] = position[0] * scale[0] + trans[0];
@@ -211,7 +223,16 @@ static boolean post_vs_viewport( struct pt_post_vs *pvs,
static boolean post_vs_none( struct pt_post_vs *pvs,
struct draw_vertex_info *info )
{
+ struct vertex_header *out = info->verts;
+ unsigned j;
+
if (0) debug_printf("%s\n", __FUNCTION__);
+ /* just initialize the vertex_id in all headers */
+ for (j = 0; j < info->count; j++) {
+ initialize_vertex_header(out);
+
+ out = (struct vertex_header *)((char *)out + info->stride);
+ }
return FALSE;
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c
index 5ea833032f..cd7bb7bf25 100644
--- a/src/gallium/auxiliary/draw/draw_pt_varray.c
+++ b/src/gallium/auxiliary/draw/draw_pt_varray.c
@@ -120,24 +120,27 @@ static void varray_fan_segment(struct varray_frontend *varray,
#define FUNC varray_run
#include "draw_pt_varray_tmp_linear.h"
-static unsigned decompose_prim[PIPE_PRIM_POLYGON + 1] = {
+static unsigned decompose_prim[PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY + 1] = {
PIPE_PRIM_POINTS,
PIPE_PRIM_LINES,
PIPE_PRIM_LINE_STRIP, /* decomposed LINELOOP */
PIPE_PRIM_LINE_STRIP,
PIPE_PRIM_TRIANGLES,
PIPE_PRIM_TRIANGLE_STRIP,
- PIPE_PRIM_TRIANGLE_FAN,
+ PIPE_PRIM_TRIANGLE_FAN,
PIPE_PRIM_QUADS,
PIPE_PRIM_QUAD_STRIP,
- PIPE_PRIM_POLYGON
+ PIPE_PRIM_POLYGON,
+ PIPE_PRIM_LINES_ADJACENCY,
+ PIPE_PRIM_LINE_STRIP_ADJACENCY,
+ PIPE_PRIM_TRIANGLES_ADJACENCY,
+ PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY
};
static void varray_prepare(struct draw_pt_front_end *frontend,
unsigned in_prim,
- unsigned out_prim,
struct draw_pt_middle_end *middle,
unsigned opt)
{
@@ -146,11 +149,13 @@ static void varray_prepare(struct draw_pt_front_end *frontend,
varray->base.run = varray_run;
varray->input_prim = in_prim;
- varray->output_prim = decompose_prim[out_prim];
+ assert(in_prim < Elements(decompose_prim));
+ varray->output_prim = decompose_prim[in_prim];
varray->middle = middle;
- middle->prepare(middle, varray->input_prim,
- varray->output_prim, opt, &varray->driver_fetch_max );
+ middle->prepare(middle,
+ varray->output_prim,
+ opt, &varray->driver_fetch_max );
/* check that the max is even */
assert((varray->driver_fetch_max & 1) == 0);
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c
index 914c87a9dc..8ef94c3163 100644
--- a/src/gallium/auxiliary/draw/draw_pt_vcache.c
+++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c
@@ -41,6 +41,7 @@
#define FETCH_MAX 256
#define DRAW_MAX (16*1024)
+
struct vcache_frontend {
struct draw_pt_front_end base;
struct draw_context *draw;
@@ -64,13 +65,13 @@ struct vcache_frontend {
unsigned opt;
};
+
static INLINE void
vcache_flush( struct vcache_frontend *vcache )
{
if (vcache->middle_prim != vcache->output_prim) {
vcache->middle_prim = vcache->output_prim;
vcache->middle->prepare( vcache->middle,
- vcache->input_prim,
vcache->middle_prim,
vcache->opt,
&vcache->fetch_max );
@@ -89,12 +90,12 @@ vcache_flush( struct vcache_frontend *vcache )
vcache->draw_count = 0;
}
+
static INLINE void
vcache_check_flush( struct vcache_frontend *vcache )
{
- if ( vcache->draw_count + 6 >= DRAW_MAX ||
- vcache->fetch_count + 4 >= FETCH_MAX )
- {
+ if (vcache->draw_count + 6 >= DRAW_MAX ||
+ vcache->fetch_count + 4 >= FETCH_MAX) {
vcache_flush( vcache );
}
}
@@ -146,6 +147,7 @@ vcache_triangle_flags( struct vcache_frontend *vcache,
vcache_check_flush(vcache);
}
+
static INLINE void
vcache_line( struct vcache_frontend *vcache,
unsigned i0,
@@ -177,6 +179,7 @@ vcache_point( struct vcache_frontend *vcache,
vcache_check_flush(vcache);
}
+
static INLINE void
vcache_quad( struct vcache_frontend *vcache,
unsigned i0,
@@ -196,6 +199,7 @@ vcache_quad( struct vcache_frontend *vcache,
}
}
+
static INLINE void
vcache_ef_quad( struct vcache_frontend *vcache,
unsigned i0,
@@ -231,6 +235,7 @@ vcache_ef_quad( struct vcache_frontend *vcache,
}
}
+
/* At least for now, we're back to using a template include file for
* this. The two paths aren't too different though - it may be
* possible to reunify them.
@@ -256,23 +261,23 @@ rebase_uint_elts( const unsigned *src,
ushort *dest )
{
unsigned i;
-
for (i = 0; i < count; i++)
dest[i] = (ushort)(src[i] + delta);
}
+
static INLINE void
rebase_ushort_elts( const ushort *src,
unsigned count,
int delta,
- ushort *dest )
+ ushort *dest )
{
unsigned i;
-
for (i = 0; i < count; i++)
dest[i] = (ushort)(src[i] + delta);
}
+
static INLINE void
rebase_ubyte_elts( const ubyte *src,
unsigned count,
@@ -280,42 +285,39 @@ rebase_ubyte_elts( const ubyte *src,
ushort *dest )
{
unsigned i;
-
for (i = 0; i < count; i++)
dest[i] = (ushort)(src[i] + delta);
}
-
static INLINE void
translate_uint_elts( const unsigned *src,
unsigned count,
ushort *dest )
{
unsigned i;
-
for (i = 0; i < count; i++)
dest[i] = (ushort)(src[i]);
}
+
static INLINE void
translate_ushort_elts( const ushort *src,
unsigned count,
ushort *dest )
{
unsigned i;
-
for (i = 0; i < count; i++)
dest[i] = (ushort)(src[i]);
}
+
static INLINE void
translate_ubyte_elts( const ubyte *src,
unsigned count,
ushort *dest )
{
unsigned i;
-
for (i = 0; i < count; i++)
dest[i] = (ushort)(src[i]);
}
@@ -336,6 +338,7 @@ format_from_get_elt( pt_elt_func get_elt )
}
#endif
+
static INLINE void
vcache_check_run( struct draw_pt_front_end *frontend,
pt_elt_func get_elt,
@@ -345,18 +348,46 @@ vcache_check_run( struct draw_pt_front_end *frontend,
{
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
struct draw_context *draw = vcache->draw;
- unsigned min_index = draw->pt.user.min_index;
- unsigned max_index = draw->pt.user.max_index;
- unsigned index_size = draw->pt.user.eltSize;
- unsigned fetch_count = max_index + 1 - min_index;
+ const unsigned min_index = draw->pt.user.min_index;
+ const unsigned max_index = draw->pt.user.max_index;
+ const unsigned index_size = draw->pt.user.eltSize;
+ unsigned fetch_count;
const ushort *transformed_elts;
ushort *storage = NULL;
boolean ok = FALSE;
+ /* debug: verify indexes are in range [min_index, max_index] */
+ if (0) {
+ unsigned i;
+ for (i = 0; i < draw_count; i++) {
+ if (index_size == 1) {
+ assert( ((const ubyte *) elts)[i] >= min_index);
+ assert( ((const ubyte *) elts)[i] <= max_index);
+ }
+ else if (index_size == 2) {
+ assert( ((const ushort *) elts)[i] >= min_index);
+ assert( ((const ushort *) elts)[i] <= max_index);
+ }
+ else {
+ assert(index_size == 4);
+ assert( ((const uint *) elts)[i] >= min_index);
+ assert( ((const uint *) elts)[i] <= max_index);
+ }
+ }
+ }
+
+ /* Note: max_index is frequently 0xffffffff so we have to be sure
+ * that any arithmetic involving max_index doesn't overflow!
+ */
+ if (max_index >= (unsigned) DRAW_PIPE_MAX_VERTICES)
+ goto fail;
- if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count,
- vcache->fetch_max,
- draw_count);
+ fetch_count = max_index + 1 - min_index;
+
+ if (0)
+ debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count,
+ vcache->fetch_max,
+ draw_count);
if (elt_bias + max_index >= DRAW_PIPE_MAX_VERTICES ||
fetch_count >= UNDEFINED_VERTEX_ID ||
@@ -368,23 +399,19 @@ vcache_check_run( struct draw_pt_front_end *frontend,
if (vcache->middle_prim != vcache->input_prim) {
vcache->middle_prim = vcache->input_prim;
vcache->middle->prepare( vcache->middle,
- vcache->input_prim,
vcache->middle_prim,
vcache->opt,
&vcache->fetch_max );
}
-
assert((elt_bias >= 0 && min_index + elt_bias >= min_index) ||
(elt_bias < 0 && min_index + elt_bias < min_index));
if (min_index == 0 &&
- index_size == 2)
- {
+ index_size == 2) {
transformed_elts = (const ushort *)elts;
}
- else
- {
+ else {
storage = MALLOC( draw_count * sizeof(ushort) );
if (!storage)
goto fail;
@@ -419,23 +446,23 @@ vcache_check_run( struct draw_pt_front_end *frontend,
switch(index_size) {
case 1:
rebase_ubyte_elts( (const ubyte *)elts,
- draw_count,
- 0 - (int)min_index,
- storage );
+ draw_count,
+ 0 - (int)min_index,
+ storage );
break;
case 2:
rebase_ushort_elts( (const ushort *)elts,
- draw_count,
- 0 - (int)min_index,
- storage );
+ draw_count,
+ 0 - (int)min_index,
+ storage );
break;
case 4:
rebase_uint_elts( (const uint *)elts,
- draw_count,
- 0 - (int)min_index,
- storage );
+ draw_count,
+ 0 - (int)min_index,
+ storage );
break;
default:
@@ -462,7 +489,7 @@ vcache_check_run( struct draw_pt_front_end *frontend,
debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
fetch_count, draw_count);
- fail:
+fail:
vcache_run( frontend, get_elt, elts, elt_bias, draw_count );
}
@@ -472,23 +499,26 @@ vcache_check_run( struct draw_pt_front_end *frontend,
static void
vcache_prepare( struct draw_pt_front_end *frontend,
unsigned in_prim,
- unsigned out_prim,
struct draw_pt_middle_end *middle,
unsigned opt )
{
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
- if (opt & PT_PIPELINE)
- {
+ if (opt & PT_PIPELINE) {
vcache->base.run = vcache_run_extras;
}
- else
- {
+ else {
vcache->base.run = vcache_check_run;
}
+ /* VCache will always emit the reduced version of its input
+ * primitive, ie STRIP/FANS become TRIS, etc.
+ *
+ * This is not to be confused with what the GS might be up to,
+ * which is a separate issue.
+ */
vcache->input_prim = in_prim;
- vcache->output_prim = u_reduced_prim(out_prim);
+ vcache->output_prim = u_reduced_prim(in_prim);
vcache->middle = middle;
vcache->opt = opt;
@@ -496,12 +526,13 @@ vcache_prepare( struct draw_pt_front_end *frontend,
/* Have to run prepare here, but try and guess a good prim for
* doing so:
*/
- vcache->middle_prim = (opt & PT_PIPELINE) ? vcache->output_prim : vcache->input_prim;
- middle->prepare( middle, vcache->input_prim,
- vcache->middle_prim, opt, &vcache->fetch_max );
-}
-
+ vcache->middle_prim = (opt & PT_PIPELINE)
+ ? vcache->output_prim : vcache->input_prim;
+ middle->prepare( middle,
+ vcache->middle_prim,
+ opt, &vcache->fetch_max );
+}
static void
@@ -512,6 +543,7 @@ vcache_finish( struct draw_pt_front_end *frontend )
vcache->middle = NULL;
}
+
static void
vcache_destroy( struct draw_pt_front_end *frontend )
{
diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c
index b9db886a24..57ea63fc06 100644
--- a/src/gallium/auxiliary/draw/draw_vs.c
+++ b/src/gallium/auxiliary/draw/draw_vs.c
@@ -98,6 +98,11 @@ draw_create_vertex_shader(struct draw_context *draw,
vs = draw_create_vs_ppc( draw, shader );
#endif
}
+#if HAVE_LLVM
+ else {
+ vs = draw_create_vs_llvm(draw, shader);
+ }
+#endif
if (!vs) {
vs = draw_create_vs_exec( draw, shader );
diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h
index 6c7e94db43..a731994523 100644
--- a/src/gallium/auxiliary/draw/draw_vs.h
+++ b/src/gallium/auxiliary/draw/draw_vs.h
@@ -165,7 +165,6 @@ draw_create_vs_ppc(struct draw_context *draw,
const struct pipe_shader_state *templ);
-
struct draw_vs_varient_key;
struct draw_vertex_shader;
@@ -173,6 +172,11 @@ struct draw_vs_varient *
draw_vs_create_varient_aos_sse( struct draw_vertex_shader *vs,
const struct draw_vs_varient_key *key );
+#if HAVE_LLVM
+struct draw_vertex_shader *
+draw_create_vs_llvm(struct draw_context *draw,
+ const struct pipe_shader_state *state);
+#endif
/********************************************************************************
diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c
new file mode 100644
index 0000000000..6c13df7913
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c
@@ -0,0 +1,120 @@
+/**************************************************************************
+ *
+ * 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 "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "draw_private.h"
+#include "draw_context.h"
+#include "draw_vs.h"
+#include "draw_llvm.h"
+
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_scan.h"
+
+static void
+vs_llvm_prepare(struct draw_vertex_shader *shader,
+ struct draw_context *draw)
+{
+ /*struct llvm_vertex_shader *evs = llvm_vertex_shader(shader);*/
+}
+
+static void
+vs_llvm_run_linear( struct draw_vertex_shader *shader,
+ const float (*input)[4],
+ float (*output)[4],
+ const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ unsigned count,
+ unsigned input_stride,
+ unsigned output_stride )
+{
+ /* we should never get here since the entire pipeline is
+ * generated in draw_pt_fetch_shade_pipeline_llvm.c */
+ debug_assert(0);
+}
+
+
+static void
+vs_llvm_delete( struct draw_vertex_shader *dvs )
+{
+ struct llvm_vertex_shader *shader = llvm_vertex_shader(dvs);
+ struct pipe_fence_handle *fence = NULL;
+ struct draw_llvm_variant_list_item *li;
+ struct pipe_context *pipe = dvs->draw->pipe;
+
+ /*
+ * XXX: This might be not neccessary at all.
+ */
+ pipe->flush(pipe, 0, &fence);
+ if (fence) {
+ pipe->screen->fence_finish(pipe->screen, fence, 0);
+ pipe->screen->fence_reference(pipe->screen, &fence, NULL);
+ }
+
+
+ li = first_elem(&shader->variants);
+ while(!at_end(&shader->variants, li)) {
+ struct draw_llvm_variant_list_item *next = next_elem(li);
+ draw_llvm_destroy_variant(li->base);
+ li = next;
+ }
+
+ assert(shader->variants_cached == 0);
+ FREE((void*) dvs->state.tokens);
+ FREE( dvs );
+}
+
+
+struct draw_vertex_shader *
+draw_create_vs_llvm(struct draw_context *draw,
+ const struct pipe_shader_state *state)
+{
+ struct llvm_vertex_shader *vs = CALLOC_STRUCT( llvm_vertex_shader );
+
+ if (vs == NULL)
+ return NULL;
+
+ /* we make a private copy of the tokens */
+ vs->base.state.tokens = tgsi_dup_tokens(state->tokens);
+ if (!vs->base.state.tokens) {
+ FREE(vs);
+ return NULL;
+ }
+
+ tgsi_scan_shader(state->tokens, &vs->base.info);
+
+ vs->base.draw = draw;
+ vs->base.prepare = vs_llvm_prepare;
+ vs->base.run_linear = vs_llvm_run_linear;
+ vs->base.delete = vs_llvm_delete;
+ vs->base.create_varient = draw_vs_create_varient_generic;
+
+ make_empty_list(&vs->variants);
+
+ return &vs->base;
+}