summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2010-06-14 10:18:09 -0400
committerZack Rusin <[email protected]>2010-07-06 13:29:04 -0400
commit01eebfe1b6de2e36dd3af0952fc8329b7073a100 (patch)
tree23f1727a4e3a8788fbf82ff6b1fd374bc4ec8b19 /src
parentce929d8210baf0ea66f32565285f0b33cd495e46 (diff)
draw: implement vertex texture sampling using llvm
Diffstat (limited to 'src')
-rw-r--r--src/gallium/auxiliary/Makefile3
-rw-r--r--src/gallium/auxiliary/SConscript3
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c56
-rw-r--r--src/gallium/auxiliary/draw/draw_context.h18
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c98
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.h42
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm_sample.c216
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h7
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c5
-rw-r--r--src/gallium/drivers/llvmpipe/lp_screen.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c73
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.h5
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_context.h4
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_derived.c8
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_sampler.c8
15 files changed, 516 insertions, 32 deletions
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
index 91f8b1034a8..731f60d2164 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 af3f47bbf01..7e06cc0c76e 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 dab95e50515..aac1ed602c7 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 c0122f2aca5..724f992783b 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 f521669fcde..42653d36ec4 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 <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);
@@ -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 1ef009b592c..05446517c6a 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 <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;
@@ -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 00000000000..2613224f75e
--- /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 <[email protected]>
+ */
+
+#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 54944a7c67a..8af885908e3 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
@@ -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 d33969ac709..6aefbede59b 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 49b13f464a7..edcab0f8d95 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 2597fa8f71b..fcb6e06123d 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,
@@ -658,6 +657,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
* being rendered and the current scene being built.
@@ -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 6a0dc551290..fd2c927c2ea 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 8f4e00f0732..947d5efe2b0 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 d20a5218d41..263b1174940 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 e94065fb6ab..0fea7f20a73 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;
}