unsigned i;
debug_assert(shader_stage < PIPE_SHADER_TYPES);
- debug_assert(num <= PIPE_MAX_SAMPLERS);
+ debug_assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
for (i = 0; i < num; ++i)
draw->sampler_views[shader_stage][i] = views[i];
- for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
+ for (i = num; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; ++i)
draw->sampler_views[shader_stage][i] = NULL;
draw->num_sampler_views[shader_stage] = num;
elem_types[DRAW_JIT_TEXTURE_IMG_STRIDE] =
elem_types[DRAW_JIT_TEXTURE_MIP_OFFSETS] =
LLVMArrayType(int32_type, PIPE_MAX_TEXTURE_LEVELS);
- elem_types[DRAW_JIT_TEXTURE_MIN_LOD] =
- elem_types[DRAW_JIT_TEXTURE_MAX_LOD] =
- elem_types[DRAW_JIT_TEXTURE_LOD_BIAS] = LLVMFloatTypeInContext(gallivm->context);
- elem_types[DRAW_JIT_TEXTURE_BORDER_COLOR] =
- LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
texture_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, mip_offsets,
target, texture_type,
DRAW_JIT_TEXTURE_MIP_OFFSETS);
- LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, min_lod,
- target, texture_type,
- DRAW_JIT_TEXTURE_MIN_LOD);
- LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, max_lod,
- target, texture_type,
- DRAW_JIT_TEXTURE_MAX_LOD);
- LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, lod_bias,
- target, texture_type,
- DRAW_JIT_TEXTURE_LOD_BIAS);
- LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, border_color,
- target, texture_type,
- DRAW_JIT_TEXTURE_BORDER_COLOR);
LP_CHECK_STRUCT_SIZE(struct draw_jit_texture, target, texture_type);
/**
- * Create LLVM type for struct draw_jit_texture
+ * Create LLVM type for struct draw_jit_sampler
+ */
+static LLVMTypeRef
+create_jit_sampler_type(struct gallivm_state *gallivm, const char *struct_name)
+{
+ LLVMTargetDataRef target = gallivm->target;
+ LLVMTypeRef sampler_type;
+ LLVMTypeRef elem_types[DRAW_JIT_SAMPLER_NUM_FIELDS];
+
+ elem_types[DRAW_JIT_SAMPLER_MIN_LOD] =
+ elem_types[DRAW_JIT_SAMPLER_MAX_LOD] =
+ elem_types[DRAW_JIT_SAMPLER_LOD_BIAS] = LLVMFloatTypeInContext(gallivm->context);
+ elem_types[DRAW_JIT_SAMPLER_BORDER_COLOR] =
+ LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
+
+ sampler_type = LLVMStructTypeInContext(gallivm->context, elem_types,
+ Elements(elem_types), 0);
+
+#if HAVE_LLVM < 0x0300
+ LLVMAddTypeName(gallivm->module, struct_name, sampler_type);
+
+ /* Make sure the target's struct layout cache doesn't return
+ * stale/invalid data.
+ */
+ LLVMInvalidateStructLayout(gallivm->target, sampler_type);
+#endif
+
+ LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, min_lod,
+ target, sampler_type,
+ DRAW_JIT_SAMPLER_MIN_LOD);
+ LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, max_lod,
+ target, sampler_type,
+ DRAW_JIT_SAMPLER_MAX_LOD);
+ LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, lod_bias,
+ target, sampler_type,
+ DRAW_JIT_SAMPLER_LOD_BIAS);
+ LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, border_color,
+ target, sampler_type,
+ DRAW_JIT_SAMPLER_BORDER_COLOR);
+
+ LP_CHECK_STRUCT_SIZE(struct draw_jit_sampler, target, sampler_type);
+
+ return sampler_type;
+}
+
+
+/**
+ * Create LLVM type for struct draw_jit_context
*/
static LLVMTypeRef
create_jit_context_type(struct gallivm_state *gallivm,
- LLVMTypeRef texture_type, const char *struct_name)
+ LLVMTypeRef texture_type, LLVMTypeRef sampler_type,
+ const char *struct_name)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef float_type = LLVMFloatTypeInContext(gallivm->context);
- LLVMTypeRef elem_types[5];
+ LLVMTypeRef elem_types[6];
LLVMTypeRef context_type;
elem_types[0] = LLVMArrayType(LLVMPointerType(float_type, 0), /* vs_constants */
DRAW_TOTAL_CLIP_PLANES), 0);
elem_types[3] = LLVMPointerType(float_type, 0); /* viewport */
elem_types[4] = LLVMArrayType(texture_type,
- PIPE_MAX_SAMPLERS); /* textures */
+ PIPE_MAX_SHADER_SAMPLER_VIEWS); /* textures */
+ elem_types[5] = LLVMArrayType(sampler_type,
+ PIPE_MAX_SAMPLERS); /* samplers */
context_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
#if HAVE_LLVM < 0x0300
target, context_type, 1);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, planes,
target, context_type, 2);
+ LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, viewport,
+ target, context_type, 3);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, textures,
target, context_type,
DRAW_JIT_CTX_TEXTURES);
+ LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, samplers,
+ target, context_type,
+ DRAW_JIT_CTX_SAMPLERS);
LP_CHECK_STRUCT_SIZE(struct draw_jit_context,
target, context_type);
create_jit_types(struct draw_llvm_variant *variant)
{
struct gallivm_state *gallivm = variant->gallivm;
- LLVMTypeRef texture_type, context_type, buffer_type, vb_type;
+ LLVMTypeRef texture_type, sampler_type, context_type, buffer_type, vb_type;
texture_type = create_jit_texture_type(gallivm, "texture");
+ sampler_type = create_jit_sampler_type(gallivm, "sampler");
- context_type = create_jit_context_type(gallivm, texture_type, "draw_jit_context");
+ context_type = create_jit_context_type(gallivm, texture_type, sampler_type,
+ "draw_jit_context");
variant->context_ptr_type = LLVMPointerType(context_type, 0);
buffer_type = LLVMPointerType(LLVMIntTypeInContext(gallivm->context, 8), 0);
{
unsigned i;
struct draw_llvm_variant_key *key;
- struct lp_sampler_static_state *sampler;
+ struct draw_sampler_static_state *draw_sampler;
key = (struct draw_llvm_variant_key *)store;
* sampler array.
*/
key->nr_samplers = llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_SAMPLER] + 1;
+ if (llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_SAMPLER_VIEW] != -1) {
+ key->nr_sampler_views =
+ llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_SAMPLER_VIEW] + 1;
+ }
+ else {
+ key->nr_sampler_views = key->nr_samplers;
+ }
- sampler = draw_llvm_variant_key_samplers(key);
+ draw_sampler = draw_llvm_variant_key_samplers(key);
memcpy(key->vertex_element,
llvm->draw->pt.vertex_element,
sizeof(struct pipe_vertex_element) * key->nr_vertex_elements);
-
- memset(sampler, 0, key->nr_samplers * sizeof *sampler);
+
+ memset(draw_sampler, 0, MAX2(key->nr_samplers, key->nr_sampler_views) * sizeof *draw_sampler);
for (i = 0 ; i < key->nr_samplers; i++) {
- lp_sampler_static_state(&sampler[i],
- llvm->draw->sampler_views[PIPE_SHADER_VERTEX][i],
- llvm->draw->samplers[PIPE_SHADER_VERTEX][i]);
+ lp_sampler_static_sampler_state(&draw_sampler[i].sampler_state,
+ llvm->draw->samplers[PIPE_SHADER_VERTEX][i]);
+ }
+ for (i = 0 ; i < key->nr_sampler_views; i++) {
+ lp_sampler_static_texture_state(&draw_sampler[i].texture_state,
+ llvm->draw->sampler_views[PIPE_SHADER_VERTEX][i]);
}
return key;
draw_llvm_dump_variant_key(struct draw_llvm_variant_key *key)
{
unsigned i;
- struct lp_sampler_static_state *sampler = draw_llvm_variant_key_samplers(key);
+ struct draw_sampler_static_state *sampler = draw_llvm_variant_key_samplers(key);
debug_printf("clamp_vertex_color = %u\n", key->clamp_vertex_color);
debug_printf("clip_xy = %u\n", key->clip_xy);
debug_printf("vertex_element[%i].src_format = %s\n", i, util_format_name(key->vertex_element[i].src_format));
}
- for (i = 0 ; i < key->nr_samplers; i++) {
- debug_printf("sampler[%i].src_format = %s\n", i, util_format_name(sampler[i].format));
+ for (i = 0 ; i < key->nr_sampler_views; i++) {
+ debug_printf("sampler[%i].src_format = %s\n", i, util_format_name(sampler[i].texture_state.format));
}
}
unsigned i;
for (i = 0; i < draw->num_samplers[PIPE_SHADER_VERTEX]; i++) {
- struct draw_jit_texture *jit_tex = &draw->llvm->jit_context.textures[i];
+ struct draw_jit_sampler *jit_sam = &draw->llvm->jit_context.samplers[i];
if (draw->samplers[i]) {
const struct pipe_sampler_state *s
= draw->samplers[PIPE_SHADER_VERTEX][i];
- jit_tex->min_lod = s->min_lod;
- jit_tex->max_lod = s->max_lod;
- jit_tex->lod_bias = s->lod_bias;
- COPY_4V(jit_tex->border_color, s->border_color.f);
+ jit_sam->min_lod = s->min_lod;
+ jit_sam->max_lod = s->max_lod;
+ jit_sam->lod_bias = s->lod_bias;
+ COPY_4V(jit_sam->border_color, s->border_color.f);
}
}
}
uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS];
+};
+
+
+struct draw_sampler_static_state
+{
+ /*
+ * These attributes are effectively interleaved for more sane key handling.
+ * However, there might be lots of null space if the amount of samplers and
+ * textures isn't the same.
+ */
+ struct lp_static_sampler_state sampler_state;
+ struct lp_static_texture_state texture_state;
+};
+
+
+struct draw_jit_sampler
+{
float min_lod;
float max_lod;
float lod_bias;
float border_color[4];
};
+
enum {
DRAW_JIT_TEXTURE_WIDTH = 0,
DRAW_JIT_TEXTURE_HEIGHT,
DRAW_JIT_TEXTURE_ROW_STRIDE,
DRAW_JIT_TEXTURE_IMG_STRIDE,
DRAW_JIT_TEXTURE_MIP_OFFSETS,
- DRAW_JIT_TEXTURE_MIN_LOD,
- DRAW_JIT_TEXTURE_MAX_LOD,
- DRAW_JIT_TEXTURE_LOD_BIAS,
- DRAW_JIT_TEXTURE_BORDER_COLOR,
DRAW_JIT_TEXTURE_NUM_FIELDS /* number of fields above */
};
+
+enum {
+ DRAW_JIT_SAMPLER_MIN_LOD,
+ DRAW_JIT_SAMPLER_MAX_LOD,
+ DRAW_JIT_SAMPLER_LOD_BIAS,
+ DRAW_JIT_SAMPLER_BORDER_COLOR,
+ DRAW_JIT_SAMPLER_NUM_FIELDS /* number of fields above */
+};
+
+
enum {
DRAW_JIT_VERTEX_VERTEX_ID = 0,
DRAW_JIT_VERTEX_CLIP,
DRAW_JIT_VERTEX_DATA
};
+#define DRAW_JIT_CTX_TEXTURES 4
+#define DRAW_JIT_CTX_SAMPLERS 5
+
/**
* This structure is passed directly to the generated vertex shader.
*
float (*planes) [DRAW_TOTAL_CLIP_PLANES][4];
float *viewport;
- struct draw_jit_texture textures[PIPE_MAX_SAMPLERS];
+ struct draw_jit_texture textures[PIPE_MAX_SHADER_SAMPLER_VIEWS];
+ struct draw_jit_sampler samplers[PIPE_MAX_SAMPLERS];
};
lp_build_struct_get(_gallivm, _ptr, 3, "viewport")
#define DRAW_JIT_CTX_TEXTURES 4
+#define DRAW_JIT_CTX_SAMPLERS 5
#define draw_jit_context_textures(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_CTX_TEXTURES, "textures")
+#define draw_jit_context_samplers(_gallivm, _ptr) \
+ lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_CTX_SAMPLERS, "samplers")
+
#define draw_jit_header_id(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_VERTEX_VERTEX_ID, "id")
{
unsigned nr_vertex_elements:8;
unsigned nr_samplers:8;
+ unsigned nr_sampler_views:8;
unsigned clamp_vertex_color:1;
unsigned clip_xy:1;
unsigned clip_z:1;
unsigned bypass_viewport:1;
unsigned need_edgeflags:1;
unsigned ucp_enable:PIPE_MAX_CLIP_PLANES;
- unsigned pad:9-PIPE_MAX_CLIP_PLANES;
+ unsigned pad:33-PIPE_MAX_CLIP_PLANES;
/* Variable number of vertex elements:
*/
/* Followed by variable number of samplers:
*/
-/* struct lp_sampler_static_state sampler; */
+/* struct draw_sampler_static_state sampler; */
};
#define DRAW_LLVM_MAX_VARIANT_KEY_SIZE \
(sizeof(struct draw_llvm_variant_key) + \
- PIPE_MAX_SAMPLERS * sizeof(struct lp_sampler_static_state) + \
+ PIPE_MAX_SHADER_SAMPLER_VIEWS * sizeof(struct draw_sampler_static_state) + \
(PIPE_MAX_ATTRIBS-1) * sizeof(struct pipe_vertex_element))
static INLINE size_t
draw_llvm_variant_key_size(unsigned nr_vertex_elements,
- unsigned nr_samplers)
+ unsigned nr_samplers)
{
return (sizeof(struct draw_llvm_variant_key) +
- nr_samplers * sizeof(struct lp_sampler_static_state) +
- (nr_vertex_elements - 1) * sizeof(struct pipe_vertex_element));
+ nr_samplers * sizeof(struct draw_sampler_static_state) +
+ (nr_vertex_elements - 1) * sizeof(struct pipe_vertex_element));
}
-static INLINE struct lp_sampler_static_state *
+static INLINE struct draw_sampler_static_state *
draw_llvm_variant_key_samplers(struct draw_llvm_variant_key *key)
{
- return (struct lp_sampler_static_state *)
+ return (struct draw_sampler_static_state *)
&key->vertex_element[key->nr_vertex_elements];
}
-
struct draw_llvm_variant_list_item
{
struct draw_llvm_variant *base;
struct draw_llvm_variant *
draw_llvm_create_variant(struct draw_llvm *llvm,
- unsigned num_vertex_header_attribs,
- const struct draw_llvm_variant_key *key);
+ unsigned num_vertex_header_attribs,
+ const struct draw_llvm_variant_key *key);
void
draw_llvm_destroy_variant(struct draw_llvm_variant *variant);
draw_llvm_dump_variant_key(struct draw_llvm_variant_key *key);
struct lp_build_sampler_soa *
-draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
+draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state,
LLVMValueRef context_ptr);
void
{
struct lp_sampler_dynamic_state base;
- const struct lp_sampler_static_state *static_state;
+ const struct draw_sampler_static_state *static_state;
LLVMValueRef context_ptr;
};
LLVMValueRef ptr;
LLVMValueRef res;
- debug_assert(unit < PIPE_MAX_SAMPLERS);
+ debug_assert(unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
/* context[0] */
indices[0] = lp_build_const_int32(gallivm, 0);
}
+/**
+ * Fetch the specified member of the lp_jit_sampler 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_sampler_member(const struct lp_sampler_dynamic_state *base,
+ struct gallivm_state *gallivm,
+ unsigned unit,
+ unsigned member_index,
+ const char *member_name,
+ boolean emit_load)
+{
+ LLVMBuilderRef builder = gallivm->builder;
+ 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_SAMPLERS);
+
+ /* context[0] */
+ indices[0] = lp_build_const_int32(gallivm, 0);
+ /* context[0].samplers */
+ indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_SAMPLERS);
+ /* context[0].samplers[unit] */
+ indices[2] = lp_build_const_int32(gallivm, unit);
+ /* context[0].samplers[unit].member */
+ indices[3] = lp_build_const_int32(gallivm, member_index);
+
+ ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
+
+ if (emit_load)
+ res = LLVMBuildLoad(builder, ptr, "");
+ else
+ res = ptr;
+
+ lp_build_name(res, "context.sampler%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
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(mip_offsets, DRAW_JIT_TEXTURE_MIP_OFFSETS, FALSE)
-DRAW_LLVM_TEXTURE_MEMBER(min_lod, DRAW_JIT_TEXTURE_MIN_LOD, TRUE)
-DRAW_LLVM_TEXTURE_MEMBER(max_lod, DRAW_JIT_TEXTURE_MAX_LOD, TRUE)
-DRAW_LLVM_TEXTURE_MEMBER(lod_bias, DRAW_JIT_TEXTURE_LOD_BIAS, TRUE)
-DRAW_LLVM_TEXTURE_MEMBER(border_color, DRAW_JIT_TEXTURE_BORDER_COLOR, FALSE)
+
+
+#define DRAW_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load) \
+ static LLVMValueRef \
+ draw_llvm_sampler_##_name( const struct lp_sampler_dynamic_state *base, \
+ struct gallivm_state *gallivm, \
+ unsigned unit) \
+ { \
+ return draw_llvm_sampler_member(base, gallivm, unit, _index, #_name, _emit_load ); \
+ }
+
+
+DRAW_LLVM_SAMPLER_MEMBER(min_lod, DRAW_JIT_SAMPLER_MIN_LOD, TRUE)
+DRAW_LLVM_SAMPLER_MEMBER(max_lod, DRAW_JIT_SAMPLER_MAX_LOD, TRUE)
+DRAW_LLVM_SAMPLER_MEMBER(lod_bias, DRAW_JIT_SAMPLER_LOD_BIAS, TRUE)
+DRAW_LLVM_SAMPLER_MEMBER(border_color, DRAW_JIT_SAMPLER_BORDER_COLOR, FALSE)
static void
struct gallivm_state *gallivm,
struct lp_type type,
boolean is_fetch,
- unsigned unit,
+ unsigned texture_index,
+ unsigned sampler_index,
const LLVMValueRef *coords,
const LLVMValueRef *offsets,
const struct lp_derivatives *derivs,
{
struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;
- assert(unit < PIPE_MAX_SAMPLERS);
+ assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
+ assert(sampler_index < PIPE_MAX_SAMPLERS);
lp_build_sample_soa(gallivm,
- &sampler->dynamic_state.static_state[unit],
+ &sampler->dynamic_state.static_state[texture_index].texture_state,
+ &sampler->dynamic_state.static_state[sampler_index].sampler_state,
&sampler->dynamic_state.base,
type,
is_fetch,
- unit,
+ texture_index,
+ sampler_index,
coords,
offsets,
derivs,
assert(unit < PIPE_MAX_SAMPLERS);
lp_build_size_query_soa(gallivm,
- &sampler->dynamic_state.static_state[unit],
+ &sampler->dynamic_state.static_state[unit].texture_state,
&sampler->dynamic_state.base,
type,
unit,
}
struct lp_build_sampler_soa *
-draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
+draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state,
LLVMValueRef context_ptr)
{
struct draw_llvm_sampler_soa *sampler;
sampler->dynamic_state.base.img_stride = draw_llvm_texture_img_stride;
sampler->dynamic_state.base.base_ptr = draw_llvm_texture_base_ptr;
sampler->dynamic_state.base.mip_offsets = draw_llvm_texture_mip_offsets;
- sampler->dynamic_state.base.min_lod = draw_llvm_texture_min_lod;
- sampler->dynamic_state.base.max_lod = draw_llvm_texture_max_lod;
- sampler->dynamic_state.base.lod_bias = draw_llvm_texture_lod_bias;
- sampler->dynamic_state.base.border_color = draw_llvm_texture_border_color;
+ sampler->dynamic_state.base.min_lod = draw_llvm_sampler_min_lod;
+ sampler->dynamic_state.base.max_lod = draw_llvm_sampler_max_lod;
+ sampler->dynamic_state.base.lod_bias = draw_llvm_sampler_lod_bias;
+ sampler->dynamic_state.base.border_color = draw_llvm_sampler_border_color;
sampler->dynamic_state.static_state = static_state;
sampler->dynamic_state.context_ptr = context_ptr;
* we only handle vertex and geometry shaders in the draw module, but
* there may be more in the future (ex: hull and tessellation).
*/
- struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
unsigned num_sampler_views[PIPE_SHADER_TYPES];
const struct pipe_sampler_state *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
unsigned num_samplers[PIPE_SHADER_TYPES];
/**
- * Initialize lp_sampler_static_state object with the gallium sampler
- * and texture state.
- * The former is considered to be static and the later dynamic.
+ * Initialize lp_sampler_static_texture_state object with the gallium
+ * texture/sampler_view state (this contains the parts which are
+ * considered static).
*/
void
-lp_sampler_static_state(struct lp_sampler_static_state *state,
- const struct pipe_sampler_view *view,
- const struct pipe_sampler_state *sampler)
+lp_sampler_static_texture_state(struct lp_static_texture_state *state,
+ const struct pipe_sampler_view *view)
{
const struct pipe_resource *texture;
memset(state, 0, sizeof *state);
- if (!sampler || !view || !view->texture)
+ if (!view || !view->texture)
return;
texture = view->texture;
+ state->format = view->format;
+ state->swizzle_r = view->swizzle_r;
+ state->swizzle_g = view->swizzle_g;
+ state->swizzle_b = view->swizzle_b;
+ state->swizzle_a = view->swizzle_a;
+
+ state->target = texture->target;
+ state->pot_width = util_is_power_of_two(texture->width0);
+ state->pot_height = util_is_power_of_two(texture->height0);
+ state->pot_depth = util_is_power_of_two(texture->depth0);
+ state->level_zero_only = !view->u.tex.last_level;
+
+ /*
+ * FIXME: Handle the remainder of pipe_sampler_view.
+ */
+}
+
+
+/**
+ * Initialize lp_sampler_static_sampler_state object with the gallium sampler
+ * state (this contains the parts which are considered static).
+ */
+void
+lp_sampler_static_sampler_state(struct lp_static_sampler_state *state,
+ const struct pipe_sampler_state *sampler)
+{
+ memset(state, 0, sizeof *state);
+
+ if (!sampler)
+ return;
+
/*
* We don't copy sampler state over unless it is actually enabled, to avoid
* spurious recompiles, as the sampler static state is part of the shader
* regarding 1D/2D/3D/CUBE textures, wrap modes, etc.
*/
- state->format = view->format;
- state->swizzle_r = view->swizzle_r;
- state->swizzle_g = view->swizzle_g;
- state->swizzle_b = view->swizzle_b;
- state->swizzle_a = view->swizzle_a;
-
- state->target = texture->target;
- state->pot_width = util_is_power_of_two(texture->width0);
- state->pot_height = util_is_power_of_two(texture->height0);
- state->pot_depth = util_is_power_of_two(texture->depth0);
-
state->wrap_s = sampler->wrap_s;
state->wrap_t = sampler->wrap_t;
state->wrap_r = sampler->wrap_r;
state->min_img_filter = sampler->min_img_filter;
state->mag_img_filter = sampler->mag_img_filter;
- if (view->u.tex.last_level && sampler->max_lod > 0.0f) {
+ if (sampler->max_lod > 0.0f) {
state->min_mip_filter = sampler->min_mip_filter;
} else {
state->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
state->apply_min_lod = 1;
}
- if (sampler->max_lod < (float)view->u.tex.last_level) {
+ /*
+ * XXX this won't do anything with the mesa state tracker which always
+ * sets max_lod to not more than actually present mip maps...
+ */
+ if (sampler->max_lod < (PIPE_MAX_TEXTURE_LEVELS - 1)) {
state->apply_max_lod = 1;
}
}
}
state->normalized_coords = sampler->normalized_coords;
-
- /*
- * FIXME: Handle the remainder of pipe_sampler_view.
- */
}
*/
static LLVMValueRef
lp_build_rho(struct lp_build_sample_context *bld,
- unsigned unit,
+ unsigned texture_unit,
const struct lp_derivatives *derivs)
{
struct gallivm_state *gallivm = bld->gallivm;
rho_vec = lp_build_max(coord_bld, rho_xvec, rho_yvec);
first_level = bld->dynamic_state->first_level(bld->dynamic_state,
- bld->gallivm, unit);
+ bld->gallivm, texture_unit);
first_level_vec = lp_build_broadcast_scalar(int_size_bld, first_level);
int_size = lp_build_minify(int_size_bld, bld->int_size, first_level_vec);
float_size = lp_build_int_to_float(float_size_bld, int_size);
*/
void
lp_build_lod_selector(struct lp_build_sample_context *bld,
- unsigned unit,
+ unsigned texture_unit,
+ unsigned sampler_unit,
const struct lp_derivatives *derivs,
LLVMValueRef lod_bias, /* optional */
LLVMValueRef explicit_lod, /* optional */
*out_lod_ipart = bld->perquadi_bld.zero;
*out_lod_fpart = perquadf_bld->zero;
- if (bld->static_state->min_max_lod_equal) {
+ if (bld->static_sampler_state->min_max_lod_equal) {
/* User is forcing sampling from a particular mipmap level.
* This is hit during mipmap generation.
*/
LLVMValueRef min_lod =
- bld->dynamic_state->min_lod(bld->dynamic_state, bld->gallivm, unit);
+ bld->dynamic_state->min_lod(bld->dynamic_state,
+ bld->gallivm, sampler_unit);
lod = lp_build_broadcast_scalar(perquadf_bld, min_lod);
}
else {
LLVMValueRef rho;
- rho = lp_build_rho(bld, unit, derivs);
+ rho = lp_build_rho(bld, texture_unit, derivs);
/*
* Compute lod = log2(rho)
*/
if (!lod_bias &&
- !bld->static_state->lod_bias_non_zero &&
- !bld->static_state->apply_max_lod &&
- !bld->static_state->apply_min_lod) {
+ !bld->static_sampler_state->lod_bias_non_zero &&
+ !bld->static_sampler_state->apply_max_lod &&
+ !bld->static_sampler_state->apply_min_lod) {
/*
* Special case when there are no post-log2 adjustments, which
* saves instructions but keeping the integer and fractional lod
}
/* add sampler lod bias */
- if (bld->static_state->lod_bias_non_zero) {
+ if (bld->static_sampler_state->lod_bias_non_zero) {
LLVMValueRef sampler_lod_bias =
- bld->dynamic_state->lod_bias(bld->dynamic_state, bld->gallivm, unit);
+ bld->dynamic_state->lod_bias(bld->dynamic_state,
+ bld->gallivm, sampler_unit);
sampler_lod_bias = lp_build_broadcast_scalar(perquadf_bld,
sampler_lod_bias);
lod = LLVMBuildFAdd(builder, lod, sampler_lod_bias, "sampler_lod_bias");
}
/* clamp lod */
- if (bld->static_state->apply_max_lod) {
+ if (bld->static_sampler_state->apply_max_lod) {
LLVMValueRef max_lod =
- bld->dynamic_state->max_lod(bld->dynamic_state, bld->gallivm, unit);
+ bld->dynamic_state->max_lod(bld->dynamic_state,
+ bld->gallivm, sampler_unit);
max_lod = lp_build_broadcast_scalar(perquadf_bld, max_lod);
lod = lp_build_min(perquadf_bld, lod, max_lod);
}
- if (bld->static_state->apply_min_lod) {
+ if (bld->static_sampler_state->apply_min_lod) {
LLVMValueRef min_lod =
- bld->dynamic_state->min_lod(bld->dynamic_state, bld->gallivm, unit);
+ bld->dynamic_state->min_lod(bld->dynamic_state,
+ bld->gallivm, sampler_unit);
min_lod = lp_build_broadcast_scalar(perquadf_bld, min_lod);
lod = lp_build_max(perquadf_bld, lod, min_lod);
ilevel);
}
if (dims == 3 ||
- bld->static_state->target == PIPE_TEXTURE_CUBE ||
- bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
- bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+ bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
+ bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
+ bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
*img_stride_vec = lp_build_get_level_stride_vec(bld,
bld->img_stride_array,
ilevel);
/**
- * Sampler static state.
+ * Texture static state.
*
- * These are the bits of state from pipe_resource and pipe_sampler_state that
+ * These are the bits of state from pipe_resource/pipe_sampler_view that
* are embedded in the generated code.
*/
-struct lp_sampler_static_state
+struct lp_static_texture_state
{
/* pipe_sampler_view's state */
enum pipe_format format;
unsigned pot_width:1; /**< is the width a power of two? */
unsigned pot_height:1;
unsigned pot_depth:1;
+ unsigned level_zero_only:1;
+};
+
+/**
+ * Sampler static state.
+ *
+ * These are the bits of state from pipe_sampler_state that
+ * are embedded in the generated code.
+ */
+struct lp_static_sampler_state
+{
/* pipe_sampler_state's state */
unsigned wrap_s:3;
unsigned wrap_t:3;
/**
* Sampler dynamic state.
*
- * These are the bits of state from pipe_resource and pipe_sampler_state that
- * are computed in runtime.
+ * These are the bits of state from pipe_resource/pipe_sampler_view
+ * as well as from sampler state that are computed at runtime.
*
* There are obtained through callbacks, as we don't want to tie the texture
* sampling code generation logic to any particular texture layout or pipe
*/
struct lp_sampler_dynamic_state
{
+ /* First callbacks for sampler view state */
/** Obtain the base texture width (returns int32) */
LLVMValueRef
struct gallivm_state *gallivm,
unsigned unit);
+ /* These are callbacks for sampler state */
+
/** Obtain texture min lod (returns float) */
LLVMValueRef
(*min_lod)(const struct lp_sampler_dynamic_state *state,
{
struct gallivm_state *gallivm;
- const struct lp_sampler_static_state *static_state;
+ const struct lp_static_texture_state *static_texture_state;
+ const struct lp_static_sampler_state *static_sampler_state;
struct lp_sampler_dynamic_state *dynamic_state;
{
unsigned char swizzles[4];
- swizzles[0] = bld->static_state->swizzle_r;
- swizzles[1] = bld->static_state->swizzle_g;
- swizzles[2] = bld->static_state->swizzle_b;
- swizzles[3] = bld->static_state->swizzle_a;
+ swizzles[0] = bld->static_texture_state->swizzle_r;
+ swizzles[1] = bld->static_texture_state->swizzle_g;
+ swizzles[2] = bld->static_texture_state->swizzle_b;
+ swizzles[3] = bld->static_texture_state->swizzle_a;
lp_build_swizzle_soa_inplace(&bld->texel_bld, texel, swizzles);
}
* Derive the sampler static state.
*/
void
-lp_sampler_static_state(struct lp_sampler_static_state *state,
- const struct pipe_sampler_view *view,
- const struct pipe_sampler_state *sampler);
+lp_sampler_static_sampler_state(struct lp_static_sampler_state *state,
+ const struct pipe_sampler_state *sampler);
+
+
+void
+lp_sampler_static_texture_state(struct lp_static_texture_state *state,
+ const struct pipe_sampler_view *view);
void
lp_build_lod_selector(struct lp_build_sample_context *bld,
- unsigned unit,
+ unsigned texture_index,
+ unsigned sampler_index,
const struct lp_derivatives *derivs,
LLVMValueRef lod_bias, /* optional */
LLVMValueRef explicit_lod, /* optional */
void
lp_build_sample_soa(struct gallivm_state *gallivm,
- const struct lp_sampler_static_state *static_state,
- struct lp_sampler_dynamic_state *dynamic_state,
+ const struct lp_static_texture_state *static_texture_state,
+ const struct lp_static_sampler_state *static_sampler_state,
+ struct lp_sampler_dynamic_state *dynamic_texture_state,
struct lp_type fp_type,
boolean is_fetch,
- unsigned unit,
+ unsigned texture_index,
+ unsigned sampler_index,
const LLVMValueRef *coords,
const LLVMValueRef *offsets,
const struct lp_derivatives *derivs,
void
lp_build_size_query_soa(struct gallivm_state *gallivm,
- const struct lp_sampler_static_state *static_state,
+ const struct lp_static_texture_state *static_state,
struct lp_sampler_dynamic_state *dynamic_state,
struct lp_type int_type,
unsigned unit,
break;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
length_minus_one = lp_build_sub(coord_bld, length, coord_bld->one);
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* scale coord to length */
coord = lp_build_mul(coord_bld, coord, length);
}
}
break;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* mul by tex size */
coord = lp_build_mul(coord_bld, coord, length);
}
s_float = s; t_float = t; r_float = r;
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
LLVMValueRef scaled_size;
LLVMValueRef flt_size;
bld->format_desc->block.width,
s_ipart, s_float,
width_vec, x_stride,
- bld->static_state->pot_width,
- bld->static_state->wrap_s,
+ bld->static_texture_state->pot_width,
+ bld->static_sampler_state->wrap_s,
&x_offset, &x_subcoord);
offset = x_offset;
if (dims >= 2) {
bld->format_desc->block.height,
t_ipart, t_float,
height_vec, row_stride_vec,
- bld->static_state->pot_height,
- bld->static_state->wrap_t,
+ bld->static_texture_state->pot_height,
+ bld->static_sampler_state->wrap_t,
&y_offset, &y_subcoord);
offset = lp_build_add(&bld->int_coord_bld, offset, y_offset);
if (dims >= 3) {
1, /* block length (depth) */
r_ipart, r_float,
depth_vec, img_stride_vec,
- bld->static_state->pot_depth,
- bld->static_state->wrap_r,
+ bld->static_texture_state->pot_depth,
+ bld->static_sampler_state->wrap_r,
&z_offset, &z_subcoord);
offset = lp_build_add(&bld->int_coord_bld, offset, z_offset);
}
}
- if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
- bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
- bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+ if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
+ bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
+ bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
LLVMValueRef z_offset;
/* The r coord is the cube face in [0,5] or array layer */
z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
/* Do texcoord wrapping */
lp_build_sample_wrap_nearest_float(bld,
s, width_vec,
- bld->static_state->pot_width,
- bld->static_state->wrap_s,
+ bld->static_texture_state->pot_width,
+ bld->static_sampler_state->wrap_s,
&x_icoord);
if (dims >= 2) {
lp_build_sample_wrap_nearest_float(bld,
t, height_vec,
- bld->static_state->pot_height,
- bld->static_state->wrap_t,
+ bld->static_texture_state->pot_height,
+ bld->static_sampler_state->wrap_t,
&y_icoord);
if (dims >= 3) {
lp_build_sample_wrap_nearest_float(bld,
r, depth_vec,
- bld->static_state->pot_depth,
- bld->static_state->wrap_r,
+ bld->static_texture_state->pot_depth,
+ bld->static_sampler_state->wrap_r,
&z_icoord);
}
}
- if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
- bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
- bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+ if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
+ bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
+ bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
z_icoord = r;
}
/*
* Linear interpolation with 8.8 fixed point.
*/
- if (bld->static_state->force_nearest_s) {
+ if (bld->static_sampler_state->force_nearest_s) {
/* special case 1-D lerp */
packed_lo = lp_build_lerp(&h16,
t_fpart_lo,
neighbors_hi[0][1][0],
neighbors_hi[0][1][0]);
}
- else if (bld->static_state->force_nearest_t) {
+ else if (bld->static_sampler_state->force_nearest_t) {
/* special case 1-D lerp */
packed_lo = lp_build_lerp(&h16,
s_fpart_lo,
s_float = s; t_float = t; r_float = r;
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
LLVMValueRef scaled_size;
LLVMValueRef flt_size;
/* subtract 0.5 (add -128) */
i32_c128 = lp_build_const_int_vec(bld->gallivm, i32.type, -128);
- if (!bld->static_state->force_nearest_s) {
+ if (!bld->static_sampler_state->force_nearest_s) {
s = LLVMBuildAdd(builder, s, i32_c128, "");
}
- if (dims >= 2 && !bld->static_state->force_nearest_t) {
+ if (dims >= 2 && !bld->static_sampler_state->force_nearest_t) {
t = LLVMBuildAdd(builder, t, i32_c128, "");
}
if (dims >= 3) {
bld->format_desc->block.width,
s_ipart, &s_fpart, s_float,
width_vec, x_stride,
- bld->static_state->pot_width,
- bld->static_state->wrap_s,
+ bld->static_texture_state->pot_width,
+ bld->static_sampler_state->wrap_s,
&x_offset0, &x_offset1,
&x_subcoord[0], &x_subcoord[1]);
/* add potential cube/array/mip offsets now as they are constant per pixel */
- if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
- bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
- bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+ if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
+ bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
+ bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
LLVMValueRef z_offset;
z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
/* The r coord is the cube face in [0,5] or array layer */
bld->format_desc->block.height,
t_ipart, &t_fpart, t_float,
height_vec, y_stride,
- bld->static_state->pot_height,
- bld->static_state->wrap_t,
+ bld->static_texture_state->pot_height,
+ bld->static_sampler_state->wrap_t,
&y_offset0, &y_offset1,
&y_subcoord[0], &y_subcoord[1]);
bld->format_desc->block.height,
r_ipart, &r_fpart, r_float,
depth_vec, z_stride,
- bld->static_state->pot_depth,
- bld->static_state->wrap_r,
+ bld->static_texture_state->pot_depth,
+ bld->static_sampler_state->wrap_r,
&z_offset0, &z_offset1,
&z_subcoord[0], &z_subcoord[1]);
for (y = 0; y < 2; y++) {
lp_build_sample_wrap_linear_float(bld,
bld->format_desc->block.width,
s, width_vec,
- bld->static_state->pot_width,
- bld->static_state->wrap_s,
+ bld->static_texture_state->pot_width,
+ bld->static_sampler_state->wrap_s,
&x_icoord0, &x_icoord1,
&s_fpart,
- bld->static_state->force_nearest_s);
+ bld->static_sampler_state->force_nearest_s);
if (dims >= 2) {
lp_build_sample_wrap_linear_float(bld,
bld->format_desc->block.height,
t, height_vec,
- bld->static_state->pot_height,
- bld->static_state->wrap_t,
+ bld->static_texture_state->pot_height,
+ bld->static_sampler_state->wrap_t,
&y_icoord0, &y_icoord1,
&t_fpart,
- bld->static_state->force_nearest_t);
+ bld->static_sampler_state->force_nearest_t);
if (dims >= 3) {
lp_build_sample_wrap_linear_float(bld,
bld->format_desc->block.height,
r, depth_vec,
- bld->static_state->pot_depth,
- bld->static_state->wrap_r,
+ bld->static_texture_state->pot_depth,
+ bld->static_sampler_state->wrap_r,
&z_icoord0, &z_icoord1,
&r_fpart, 0);
}
&x_offset1, &x_subcoord[1]);
/* add potential cube/array/mip offsets now as they are constant per pixel */
- if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
- bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
- bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+ if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
+ bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
+ bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
LLVMValueRef z_offset;
z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
/* The r coord is the cube face in [0,5] or array layer */
{
struct lp_build_context *int_bld = &bld->int_bld;
LLVMBuilderRef builder = bld->gallivm->builder;
- const unsigned mip_filter = bld->static_state->min_mip_filter;
- const unsigned min_filter = bld->static_state->min_img_filter;
- const unsigned mag_filter = bld->static_state->mag_img_filter;
+ const unsigned mip_filter = bld->static_sampler_state->min_mip_filter;
+ const unsigned min_filter = bld->static_sampler_state->min_img_filter;
+ const unsigned mag_filter = bld->static_sampler_state->mag_img_filter;
const unsigned dims = bld->dims;
LLVMValueRef packed, packed_lo, packed_hi;
LLVMValueRef unswizzled[4];
struct lp_build_context h16_bld;
/* we only support the common/simple wrap modes at this time */
- assert(lp_is_simple_wrap_mode(bld->static_state->wrap_s));
+ assert(lp_is_simple_wrap_mode(bld->static_sampler_state->wrap_s));
if (dims >= 2)
- assert(lp_is_simple_wrap_mode(bld->static_state->wrap_t));
+ assert(lp_is_simple_wrap_mode(bld->static_sampler_state->wrap_t));
if (dims >= 3)
- assert(lp_is_simple_wrap_mode(bld->static_state->wrap_r));
+ assert(lp_is_simple_wrap_mode(bld->static_sampler_state->wrap_r));
/* make 16-bit fixed-pt builder context */
LLVMValueRef mipoffsets,
LLVMValueRef texel_out[4])
{
- const struct lp_sampler_static_state *static_state = bld->static_state;
+ const struct lp_static_sampler_state *static_state = bld->static_sampler_state;
const unsigned dims = bld->dims;
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
LLVMBuilderRef builder = bld->gallivm->builder;
break;
case PIPE_TEX_WRAP_CLAMP:
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* scale coord to length */
coord = lp_build_mul(coord_bld, coord, length_f);
}
struct lp_build_context abs_coord_bld = bld->coord_bld;
abs_coord_bld.type.sign = FALSE;
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* mul by tex size */
coord = lp_build_mul(coord_bld, coord, length_f);
}
}
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* scale coord to length */
coord = lp_build_mul(coord_bld, coord, length_f);
}
case PIPE_TEX_WRAP_MIRROR_CLAMP:
coord = lp_build_abs(coord_bld, coord);
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* scale coord to length */
coord = lp_build_mul(coord_bld, coord, length_f);
}
abs_coord_bld.type.sign = FALSE;
coord = lp_build_abs(coord_bld, coord);
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* scale coord to length */
coord = lp_build_mul(coord_bld, coord, length_f);
}
{
coord = lp_build_abs(coord_bld, coord);
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* scale coord to length */
coord = lp_build_mul(coord_bld, coord, length_f);
}
case PIPE_TEX_WRAP_CLAMP:
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* scale coord to length */
coord = lp_build_mul(coord_bld, coord, length_f);
}
break;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* scale coord to length */
coord = lp_build_mul(coord_bld, coord, length_f);
}
coord = lp_build_coord_mirror(bld, coord);
/* scale coord to length */
- assert(bld->static_state->normalized_coords);
+ assert(bld->static_sampler_state->normalized_coords);
coord = lp_build_mul(coord_bld, coord, length_f);
/* itrunc == ifloor here */
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
coord = lp_build_abs(coord_bld, coord);
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* scale coord to length */
coord = lp_build_mul(coord_bld, coord, length_f);
}
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
coord = lp_build_abs(coord_bld, coord);
- if (bld->static_state->normalized_coords) {
+ if (bld->static_sampler_state->normalized_coords) {
/* scale coord to length */
coord = lp_build_mul(coord_bld, coord, length_f);
}
* Compute integer texcoords.
*/
x = lp_build_sample_wrap_nearest(bld, s, width_vec, flt_width_vec,
- bld->static_state->pot_width,
- bld->static_state->wrap_s);
+ bld->static_texture_state->pot_width,
+ bld->static_sampler_state->wrap_s);
lp_build_name(x, "tex.x.wrapped");
if (dims >= 2) {
y = lp_build_sample_wrap_nearest(bld, t, height_vec, flt_height_vec,
- bld->static_state->pot_height,
- bld->static_state->wrap_t);
+ bld->static_texture_state->pot_height,
+ bld->static_sampler_state->wrap_t);
lp_build_name(y, "tex.y.wrapped");
if (dims == 3) {
z = lp_build_sample_wrap_nearest(bld, r, depth_vec, flt_depth_vec,
- bld->static_state->pot_depth,
- bld->static_state->wrap_r);
+ bld->static_texture_state->pot_depth,
+ bld->static_sampler_state->wrap_r);
lp_build_name(z, "tex.z.wrapped");
}
}
- if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
- bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
- bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+ if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
+ bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
+ bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
z = r;
lp_build_name(z, "tex.z.layer");
}
* Compute integer texcoords.
*/
lp_build_sample_wrap_linear(bld, s, width_vec, flt_width_vec,
- bld->static_state->pot_width,
- bld->static_state->wrap_s,
+ bld->static_texture_state->pot_width,
+ bld->static_sampler_state->wrap_s,
&x0, &x1, &s_fpart);
lp_build_name(x0, "tex.x0.wrapped");
lp_build_name(x1, "tex.x1.wrapped");
if (dims >= 2) {
lp_build_sample_wrap_linear(bld, t, height_vec, flt_height_vec,
- bld->static_state->pot_height,
- bld->static_state->wrap_t,
+ bld->static_texture_state->pot_height,
+ bld->static_sampler_state->wrap_t,
&y0, &y1, &t_fpart);
lp_build_name(y0, "tex.y0.wrapped");
lp_build_name(y1, "tex.y1.wrapped");
if (dims == 3) {
lp_build_sample_wrap_linear(bld, r, depth_vec, flt_depth_vec,
- bld->static_state->pot_depth,
- bld->static_state->wrap_r,
+ bld->static_texture_state->pot_depth,
+ bld->static_sampler_state->wrap_r,
&z0, &z1, &r_fpart);
lp_build_name(z0, "tex.z0.wrapped");
lp_build_name(z1, "tex.z1.wrapped");
}
}
- if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
- bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
- bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+ if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
+ bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
+ bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
z0 = z1 = r; /* cube face or array layer */
lp_build_name(z0, "tex.z0.layer");
lp_build_name(z1, "tex.z1.layer");
*/
static void
lp_build_sample_common(struct lp_build_sample_context *bld,
- unsigned unit,
+ unsigned texture_index,
+ unsigned sampler_index,
LLVMValueRef *s,
LLVMValueRef *t,
LLVMValueRef *r,
LLVMValueRef *ilevel0,
LLVMValueRef *ilevel1)
{
- const unsigned mip_filter = bld->static_state->min_mip_filter;
- const unsigned min_filter = bld->static_state->min_img_filter;
- const unsigned mag_filter = bld->static_state->mag_img_filter;
- const unsigned target = bld->static_state->target;
+ const unsigned mip_filter = bld->static_sampler_state->min_mip_filter;
+ const unsigned min_filter = bld->static_sampler_state->min_img_filter;
+ const unsigned mag_filter = bld->static_sampler_state->mag_img_filter;
+ const unsigned target = bld->static_texture_state->target;
LLVMValueRef first_level;
struct lp_derivatives face_derivs;
}
else if (target == PIPE_TEXTURE_1D_ARRAY) {
*r = lp_build_iround(&bld->coord_bld, *t);
- *r = lp_build_layer_coord(bld, unit, *r);
+ *r = lp_build_layer_coord(bld, texture_index, *r);
}
else if (target == PIPE_TEXTURE_2D_ARRAY) {
*r = lp_build_iround(&bld->coord_bld, *r);
- *r = lp_build_layer_coord(bld, unit, *r);
+ *r = lp_build_layer_coord(bld, texture_index, *r);
}
/*
/* Need to compute lod either to choose mipmap levels or to
* distinguish between minification/magnification with one mipmap level.
*/
- lp_build_lod_selector(bld, unit, derivs,
- lod_bias, explicit_lod,
+ lp_build_lod_selector(bld, texture_index, sampler_index,
+ derivs, lod_bias, explicit_lod,
mip_filter,
lod_ipart, lod_fpart);
} else {
* XXX should probably disable that on other llvm versions.
*/
assert(*lod_ipart);
- lp_build_nearest_mip_level(bld, unit, *lod_ipart, ilevel0);
+ lp_build_nearest_mip_level(bld, texture_index, *lod_ipart, ilevel0);
}
else {
first_level = bld->dynamic_state->first_level(bld->dynamic_state,
- bld->gallivm, unit);
+ bld->gallivm, texture_index);
first_level = lp_build_broadcast_scalar(&bld->perquadi_bld, first_level);
*ilevel0 = first_level;
}
break;
case PIPE_TEX_MIPFILTER_NEAREST:
assert(*lod_ipart);
- lp_build_nearest_mip_level(bld, unit, *lod_ipart, ilevel0);
+ lp_build_nearest_mip_level(bld, texture_index, *lod_ipart, ilevel0);
break;
case PIPE_TEX_MIPFILTER_LINEAR:
assert(*lod_ipart);
assert(*lod_fpart);
- lp_build_linear_mip_levels(bld, unit,
+ lp_build_linear_mip_levels(bld, texture_index,
*lod_ipart, lod_fpart,
ilevel0, ilevel1);
break;
{
struct lp_build_context *int_bld = &bld->int_bld;
LLVMBuilderRef builder = bld->gallivm->builder;
- const unsigned mip_filter = bld->static_state->min_mip_filter;
- const unsigned min_filter = bld->static_state->min_img_filter;
- const unsigned mag_filter = bld->static_state->mag_img_filter;
+ const unsigned mip_filter = bld->static_sampler_state->min_mip_filter;
+ const unsigned min_filter = bld->static_sampler_state->min_img_filter;
+ const unsigned mag_filter = bld->static_sampler_state->mag_img_filter;
LLVMValueRef texels[4];
unsigned chan;
struct lp_build_context *perquadi_bld = &bld->perquadi_bld;
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
unsigned dims = bld->dims, chan;
- unsigned target = bld->static_state->target;
+ unsigned target = bld->static_texture_state->target;
LLVMValueRef size, ilevel;
LLVMValueRef row_stride_vec = NULL, img_stride_vec = NULL;
LLVMValueRef x = coords[0], y = coords[1], z = coords[2];
LLVMValueRef offset, out_of_bounds, out1;
/* XXX just like ordinary sampling, we don't handle per-pixel lod (yet). */
- if (explicit_lod && bld->static_state->target != PIPE_BUFFER) {
+ if (explicit_lod && bld->static_texture_state->target != PIPE_BUFFER) {
ilevel = lp_build_pack_aos_scalars(bld->gallivm, int_coord_bld->type,
perquadi_bld->type, explicit_lod, 0);
lp_build_nearest_mip_level(bld, unit, ilevel, &ilevel);
x, y, z, row_stride_vec, img_stride_vec,
&offset, &i, &j);
- if (bld->static_state->target != PIPE_BUFFER) {
+ if (bld->static_texture_state->target != PIPE_BUFFER) {
offset = lp_build_add(int_coord_bld, offset,
lp_build_get_mip_offsets(bld, ilevel));
}
LLVMValueRef res, p;
const unsigned chan = 0;
- if (bld->static_state->compare_mode == PIPE_TEX_COMPARE_NONE)
+ if (bld->static_sampler_state->compare_mode == PIPE_TEX_COMPARE_NONE)
return;
- if (bld->static_state->target == PIPE_TEXTURE_2D_ARRAY ||
- bld->static_state->target == PIPE_TEXTURE_CUBE) {
+ if (bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY ||
+ bld->static_texture_state->target == PIPE_TEXTURE_CUBE) {
p = coords[3];
}
else {
bld->coord_bld.one);
/* result = (p FUNC texel) ? 1 : 0 */
- res = lp_build_cmp(texel_bld, bld->static_state->compare_func,
+ res = lp_build_cmp(texel_bld, bld->static_sampler_state->compare_func,
p, texel[chan]);
res = lp_build_select(texel_bld, res, texel_bld->one, texel_bld->zero);
*/
void
lp_build_sample_soa(struct gallivm_state *gallivm,
- const struct lp_sampler_static_state *static_state,
+ const struct lp_static_texture_state *static_texture_state,
+ const struct lp_static_sampler_state *static_sampler_state,
struct lp_sampler_dynamic_state *dynamic_state,
struct lp_type type,
boolean is_fetch,
- unsigned unit,
+ unsigned texture_index,
+ unsigned sampler_index,
const LLVMValueRef *coords,
const LLVMValueRef *offsets,
const struct lp_derivatives *derivs,
LLVMValueRef explicit_lod, /* optional */
LLVMValueRef texel_out[4])
{
- unsigned dims = texture_dims(static_state->target);
+ unsigned dims = texture_dims(static_texture_state->target);
unsigned num_quads = type.length / 4;
- unsigned mip_filter = static_state->min_mip_filter;
+ unsigned mip_filter;
struct lp_build_sample_context bld;
+ struct lp_static_sampler_state derived_sampler_state = *static_sampler_state;
LLVMTypeRef i32t = LLVMInt32TypeInContext(gallivm->context);
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef tex_width, tex_height, tex_depth;
LLVMValueRef r;
if (0) {
- enum pipe_format fmt = static_state->format;
+ enum pipe_format fmt = static_texture_state->format;
debug_printf("Sample from %s\n", util_format_name(fmt));
}
/* Setup our build context */
memset(&bld, 0, sizeof bld);
bld.gallivm = gallivm;
- bld.static_state = static_state;
+ bld.static_sampler_state = &derived_sampler_state;
+ bld.static_texture_state = static_texture_state;
bld.dynamic_state = dynamic_state;
- bld.format_desc = util_format_description(static_state->format);
+ bld.format_desc = util_format_description(static_texture_state->format);
bld.dims = dims;
bld.vector_width = lp_type_width(type);
}
}
+ if (!static_texture_state->level_zero_only) {
+ derived_sampler_state.min_mip_filter = static_sampler_state->min_mip_filter;
+ } else {
+ derived_sampler_state.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ }
+ mip_filter = derived_sampler_state.min_mip_filter;
+
+ if (0) {
+ debug_printf(" .min_mip_filter = %u\n", derived_sampler_state.min_mip_filter);
+ }
+
/*
* There are other situations where at least the multiple int lods could be
* avoided like min and max lod being equal.
*/
- if ((is_fetch && explicit_lod && bld.static_state->target != PIPE_BUFFER) ||
+ if ((is_fetch && explicit_lod && bld.static_texture_state->target != PIPE_BUFFER) ||
(!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE)) {
bld.num_lods = num_quads;
}
lp_build_context_init(&bld.perquadi_bld, gallivm, bld.perquadi_type);
/* Get the dynamic state */
- tex_width = dynamic_state->width(dynamic_state, gallivm, unit);
- tex_height = dynamic_state->height(dynamic_state, gallivm, unit);
- tex_depth = dynamic_state->depth(dynamic_state, gallivm, unit);
- bld.row_stride_array = dynamic_state->row_stride(dynamic_state, gallivm, unit);
- bld.img_stride_array = dynamic_state->img_stride(dynamic_state, gallivm, unit);
- bld.base_ptr = dynamic_state->base_ptr(dynamic_state, gallivm, unit);
- bld.mip_offsets = dynamic_state->mip_offsets(dynamic_state, gallivm, unit);
+ tex_width = dynamic_state->width(dynamic_state, gallivm, texture_index);
+ tex_height = dynamic_state->height(dynamic_state, gallivm, texture_index);
+ tex_depth = dynamic_state->depth(dynamic_state, gallivm, texture_index);
+ bld.row_stride_array = dynamic_state->row_stride(dynamic_state, gallivm, texture_index);
+ bld.img_stride_array = dynamic_state->img_stride(dynamic_state, gallivm, texture_index);
+ bld.base_ptr = dynamic_state->base_ptr(dynamic_state, gallivm, texture_index);
+ bld.mip_offsets = dynamic_state->mip_offsets(dynamic_state, gallivm, texture_index);
/* Note that mip_offsets is an array[level] of offsets to texture images */
s = coords[0];
}
else if (is_fetch) {
- lp_build_fetch_texel(&bld, unit, coords,
+ lp_build_fetch_texel(&bld, texture_index, coords,
explicit_lod, offsets,
texel_out);
}
LLVMValueRef lod_ipart = NULL, lod_fpart = NULL;
LLVMValueRef ilevel0 = NULL, ilevel1 = NULL;
boolean use_aos = util_format_fits_8unorm(bld.format_desc) &&
- lp_is_simple_wrap_mode(static_state->wrap_s) &&
- lp_is_simple_wrap_mode(static_state->wrap_t);
+ lp_is_simple_wrap_mode(static_sampler_state->wrap_s) &&
+ lp_is_simple_wrap_mode(static_sampler_state->wrap_t);
if ((gallivm_debug & GALLIVM_DEBUG_PERF) &&
!use_aos && util_format_fits_8unorm(bld.format_desc)) {
debug_printf("%s: using floating point linear filtering for %s\n",
__FUNCTION__, bld.format_desc->short_name);
debug_printf(" min_img %d mag_img %d mip %d wraps %d wrapt %d\n",
- static_state->min_img_filter,
- static_state->mag_img_filter,
- static_state->min_mip_filter,
- static_state->wrap_s,
- static_state->wrap_t);
+ static_sampler_state->min_img_filter,
+ static_sampler_state->mag_img_filter,
+ static_sampler_state->min_mip_filter,
+ static_sampler_state->wrap_s,
+ static_sampler_state->wrap_t);
}
- lp_build_sample_common(&bld, unit,
+ lp_build_sample_common(&bld, texture_index, sampler_index,
&s, &t, &r,
derivs, lod_bias, explicit_lod,
&lod_ipart, &lod_fpart,
}
if (use_aos) {
/* do sampling/filtering with fixed pt arithmetic */
- lp_build_sample_aos(&bld, unit,
+ lp_build_sample_aos(&bld, sampler_index,
s, t, r,
lod_ipart, lod_fpart,
ilevel0, ilevel1,
}
else {
- lp_build_sample_general(&bld, unit,
+ lp_build_sample_general(&bld, sampler_index,
s, t, r,
lod_ipart, lod_fpart,
ilevel0, ilevel1,
/* Setup our build context */
memset(&bld4, 0, sizeof bld4);
bld4.gallivm = bld.gallivm;
- bld4.static_state = bld.static_state;
+ bld4.static_texture_state = bld.static_texture_state;
+ bld4.static_sampler_state = bld.static_sampler_state;
bld4.dynamic_state = bld.dynamic_state;
bld4.format_desc = bld.format_desc;
bld4.dims = bld.dims;
if (use_aos) {
/* do sampling/filtering with fixed pt arithmetic */
- lp_build_sample_aos(&bld4, unit,
+ lp_build_sample_aos(&bld4, sampler_index,
s4, t4, r4,
lod_iparts, lod_fparts,
ilevel0s, ilevel1s,
}
else {
- lp_build_sample_general(&bld4, unit,
+ lp_build_sample_general(&bld4, sampler_index,
s4, t4, r4,
lod_iparts, lod_fparts,
ilevel0s, ilevel1s,
lp_build_sample_compare(&bld, coords, texel_out);
}
- if (static_state->target != PIPE_BUFFER) {
+ if (static_texture_state->target != PIPE_BUFFER) {
apply_sampler_swizzle(&bld, texel_out);
}
void
lp_build_size_query_soa(struct gallivm_state *gallivm,
- const struct lp_sampler_static_state *static_state,
+ const struct lp_static_texture_state *static_state,
struct lp_sampler_dynamic_state *dynamic_state,
struct lp_type int_type,
unsigned unit,
struct gallivm_state *gallivm,
struct lp_type type,
boolean is_fetch,
- unsigned unit,
+ unsigned texture_index,
+ unsigned sampler_index,
const LLVMValueRef *coords,
const LLVMValueRef *offsets,
const struct lp_derivatives *derivs,
bld->bld_base.base.gallivm,
bld->bld_base.base.type,
FALSE,
- unit, coords,
+ unit, unit,
+ coords,
offsets,
&derivs,
lod_bias, explicit_lod,
bld->bld_base.base.gallivm,
bld->bld_base.base.type,
TRUE,
- unit, coords,
+ unit, unit,
+ coords,
offsets,
&derivs,
NULL, explicit_lod,
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
- struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
struct pipe_index_buffer index_buffer;
- struct pipe_resource *mapped_vs_tex[PIPE_MAX_SAMPLERS];
+ struct pipe_resource *mapped_vs_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS];
unsigned num_samplers[PIPE_SHADER_TYPES];
unsigned num_sampler_views[PIPE_SHADER_TYPES];
{
struct gallivm_state *gallivm = lp->gallivm;
LLVMContextRef lc = gallivm->context;
- LLVMTypeRef texture_type;
+ LLVMTypeRef texture_type, sampler_type;
/* struct lp_jit_texture */
{
elem_types[LP_JIT_TEXTURE_IMG_STRIDE] =
elem_types[LP_JIT_TEXTURE_MIP_OFFSETS] =
LLVMArrayType(LLVMInt32TypeInContext(lc), LP_MAX_TEXTURE_LEVELS);
- elem_types[LP_JIT_TEXTURE_MIN_LOD] =
- elem_types[LP_JIT_TEXTURE_MAX_LOD] =
- elem_types[LP_JIT_TEXTURE_LOD_BIAS] = LLVMFloatTypeInContext(lc);
- elem_types[LP_JIT_TEXTURE_BORDER_COLOR] =
- LLVMArrayType(LLVMFloatTypeInContext(lc), 4);
texture_type = LLVMStructTypeInContext(lc, elem_types,
Elements(elem_types), 0);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, mip_offsets,
gallivm->target, texture_type,
LP_JIT_TEXTURE_MIP_OFFSETS);
- LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, min_lod,
+ LP_CHECK_STRUCT_SIZE(struct lp_jit_texture,
+ gallivm->target, texture_type);
+ }
+
+ {
+ /* struct lp_jit_sampler */
+ LLVMTypeRef elem_types[LP_JIT_SAMPLER_NUM_FIELDS];
+ elem_types[LP_JIT_SAMPLER_MIN_LOD] =
+ elem_types[LP_JIT_SAMPLER_MAX_LOD] =
+ elem_types[LP_JIT_SAMPLER_LOD_BIAS] = LLVMFloatTypeInContext(lc);
+ elem_types[LP_JIT_SAMPLER_BORDER_COLOR] =
+ LLVMArrayType(LLVMFloatTypeInContext(lc), 4);
+
+ sampler_type = LLVMStructTypeInContext(lc, elem_types,
+ Elements(elem_types), 0);
+#if HAVE_LLVM < 0x0300
+ LLVMAddTypeName(gallivm->module, "texture", texture_type);
+
+ LLVMInvalidateStructLayout(gallivm->target, texture_type);
+#endif
+
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, min_lod,
gallivm->target, texture_type,
- LP_JIT_TEXTURE_MIN_LOD);
- LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, max_lod,
+ LP_JIT_SAMPLER_MIN_LOD);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, max_lod,
gallivm->target, texture_type,
- LP_JIT_TEXTURE_MAX_LOD);
- LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, lod_bias,
+ LP_JIT_SAMPLER_MAX_LOD);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, lod_bias,
gallivm->target, texture_type,
- LP_JIT_TEXTURE_LOD_BIAS);
- LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, border_color,
+ LP_JIT_SAMPLER_LOD_BIAS);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, border_color,
gallivm->target, texture_type,
- LP_JIT_TEXTURE_BORDER_COLOR);
-
- LP_CHECK_STRUCT_SIZE(struct lp_jit_texture,
- gallivm->target, texture_type);
+ LP_JIT_SAMPLER_BORDER_COLOR);
+ LP_CHECK_STRUCT_SIZE(struct lp_jit_sampler,
+ gallivm->target, sampler_type);
}
/* struct lp_jit_context */
elem_types[LP_JIT_CTX_U8_BLEND_COLOR] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
elem_types[LP_JIT_CTX_F_BLEND_COLOR] = LLVMPointerType(LLVMFloatTypeInContext(lc), 0);
elem_types[LP_JIT_CTX_TEXTURES] = LLVMArrayType(texture_type,
+ PIPE_MAX_SHADER_SAMPLER_VIEWS);
+ elem_types[LP_JIT_CTX_SAMPLERS] = LLVMArrayType(sampler_type,
PIPE_MAX_SAMPLERS);
context_type = LLVMStructTypeInContext(lc, elem_types,
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures,
gallivm->target, context_type,
LP_JIT_CTX_TEXTURES);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, samplers,
+ gallivm->target, context_type,
+ LP_JIT_CTX_SAMPLERS);
LP_CHECK_STRUCT_SIZE(struct lp_jit_context,
gallivm->target, context_type);
uint32_t row_stride[LP_MAX_TEXTURE_LEVELS];
uint32_t img_stride[LP_MAX_TEXTURE_LEVELS];
uint32_t mip_offsets[LP_MAX_TEXTURE_LEVELS];
- /* sampler state, actually */
+};
+
+
+struct lp_jit_sampler
+{
float min_lod;
float max_lod;
float lod_bias;
LP_JIT_TEXTURE_ROW_STRIDE,
LP_JIT_TEXTURE_IMG_STRIDE,
LP_JIT_TEXTURE_MIP_OFFSETS,
- LP_JIT_TEXTURE_MIN_LOD,
- LP_JIT_TEXTURE_MAX_LOD,
- LP_JIT_TEXTURE_LOD_BIAS,
- LP_JIT_TEXTURE_BORDER_COLOR,
LP_JIT_TEXTURE_NUM_FIELDS /* number of fields above */
};
+enum {
+ LP_JIT_SAMPLER_MIN_LOD,
+ LP_JIT_SAMPLER_MAX_LOD,
+ LP_JIT_SAMPLER_LOD_BIAS,
+ LP_JIT_SAMPLER_BORDER_COLOR,
+ LP_JIT_SAMPLER_NUM_FIELDS /* number of fields above */
+};
+
/**
* This structure is passed directly to the generated fragment shader.
uint8_t *u8_blend_color;
float *f_blend_color;
- struct lp_jit_texture textures[PIPE_MAX_SAMPLERS];
+ struct lp_jit_texture textures[PIPE_MAX_SHADER_SAMPLER_VIEWS];
+ struct lp_jit_sampler samplers[PIPE_MAX_SAMPLERS];
};
LP_JIT_CTX_U8_BLEND_COLOR,
LP_JIT_CTX_F_BLEND_COLOR,
LP_JIT_CTX_TEXTURES,
+ LP_JIT_CTX_SAMPLERS,
LP_JIT_CTX_COUNT
};
#define lp_jit_context_textures(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_TEXTURES, "textures")
+#define lp_jit_context_samplers(_gallivm, _ptr) \
+ lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_SAMPLERS, "samplers")
/**
LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
- assert(num <= PIPE_MAX_SAMPLERS);
+ assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
- for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
struct pipe_sampler_view *view = i < num ? views[i] : NULL;
if (view) {
const struct pipe_sampler_state *sampler = i < num ? samplers[i] : NULL;
if (sampler) {
- struct lp_jit_texture *jit_tex;
- jit_tex = &setup->fs.current.jit_context.textures[i];
+ struct lp_jit_sampler *jit_sam;
+ jit_sam = &setup->fs.current.jit_context.samplers[i];
- jit_tex->min_lod = sampler->min_lod;
- jit_tex->max_lod = sampler->max_lod;
- jit_tex->lod_bias = sampler->lod_bias;
- COPY_4V(jit_tex->border_color, sampler->border_color.f);
+ jit_sam->min_lod = sampler->min_lod;
+ jit_sam->max_lod = sampler->max_lod;
+ jit_sam->lod_bias = sampler->lod_bias;
+ COPY_4V(jit_sam->border_color, sampler->border_color.f);
}
}
struct {
const struct lp_rast_state *stored; /**< what's in the scene */
struct lp_rast_state current; /**< currently set state */
- struct pipe_resource *current_tex[PIPE_MAX_SAMPLERS];
+ struct pipe_resource *current_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS];
} fs;
/** fragment shader constants */
LLVMPositionBuilderAtEnd(builder, block);
/* code generated texture sampling */
- sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr);
+ sampler = lp_llvm_sampler_soa_create(key->state, context_ptr);
zs_format_desc = util_format_description(key->zsbuf_format);
}
debug_printf("blend.colormask = 0x%x\n", key->blend.rt[0].colormask);
for (i = 0; i < key->nr_samplers; ++i) {
+ const struct lp_static_sampler_state *sampler = &key->state[i].sampler_state;
debug_printf("sampler[%u] = \n", i);
- debug_printf(" .format = %s\n",
- util_format_name(key->sampler[i].format));
- debug_printf(" .target = %s\n",
- util_dump_tex_target(key->sampler[i].target, TRUE));
- debug_printf(" .pot = %u %u %u\n",
- key->sampler[i].pot_width,
- key->sampler[i].pot_height,
- key->sampler[i].pot_depth);
debug_printf(" .wrap = %s %s %s\n",
- util_dump_tex_wrap(key->sampler[i].wrap_s, TRUE),
- util_dump_tex_wrap(key->sampler[i].wrap_t, TRUE),
- util_dump_tex_wrap(key->sampler[i].wrap_r, TRUE));
+ util_dump_tex_wrap(sampler->wrap_s, TRUE),
+ util_dump_tex_wrap(sampler->wrap_t, TRUE),
+ util_dump_tex_wrap(sampler->wrap_r, TRUE));
debug_printf(" .min_img_filter = %s\n",
- util_dump_tex_filter(key->sampler[i].min_img_filter, TRUE));
+ util_dump_tex_filter(sampler->min_img_filter, TRUE));
debug_printf(" .min_mip_filter = %s\n",
- util_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE));
+ util_dump_tex_mipfilter(sampler->min_mip_filter, TRUE));
debug_printf(" .mag_img_filter = %s\n",
- util_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE));
- if (key->sampler[i].compare_mode != PIPE_TEX_COMPARE_NONE)
- debug_printf(" .compare_func = %s\n", util_dump_func(key->sampler[i].compare_func, TRUE));
- debug_printf(" .normalized_coords = %u\n", key->sampler[i].normalized_coords);
- debug_printf(" .min_max_lod_equal = %u\n", key->sampler[i].min_max_lod_equal);
- debug_printf(" .lod_bias_non_zero = %u\n", key->sampler[i].lod_bias_non_zero);
- debug_printf(" .apply_min_lod = %u\n", key->sampler[i].apply_min_lod);
- debug_printf(" .apply_max_lod = %u\n", key->sampler[i].apply_max_lod);
+ util_dump_tex_filter(sampler->mag_img_filter, TRUE));
+ if (sampler->compare_mode != PIPE_TEX_COMPARE_NONE)
+ debug_printf(" .compare_func = %s\n", util_dump_func(sampler->compare_func, TRUE));
+ debug_printf(" .normalized_coords = %u\n", sampler->normalized_coords);
+ debug_printf(" .min_max_lod_equal = %u\n", sampler->min_max_lod_equal);
+ debug_printf(" .lod_bias_non_zero = %u\n", sampler->lod_bias_non_zero);
+ debug_printf(" .apply_min_lod = %u\n", sampler->apply_min_lod);
+ debug_printf(" .apply_max_lod = %u\n", sampler->apply_max_lod);
+ }
+ for (i = 0; i < key->nr_sampler_views; ++i) {
+ const struct lp_static_texture_state *texture = &key->state[i].texture_state;
+ debug_printf("texture[%u] = \n", i);
+ debug_printf(" .format = %s\n",
+ util_format_name(texture->format));
+ debug_printf(" .target = %s\n",
+ util_dump_tex_target(texture->target, TRUE));
+ debug_printf(" .level_zero_only = %u\n",
+ texture->level_zero_only);
+ debug_printf(" .pot = %u %u %u\n",
+ texture->pot_width,
+ texture->pot_height,
+ texture->pot_depth);
}
}
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
struct lp_fragment_shader *shader;
int nr_samplers;
+ int nr_sampler_views;
int i;
shader = CALLOC_STRUCT(lp_fragment_shader);
}
nr_samplers = shader->info.base.file_max[TGSI_FILE_SAMPLER] + 1;
+ nr_sampler_views = shader->info.base.file_max[TGSI_FILE_SAMPLER_VIEW] + 1;
shader->variant_key_size = Offset(struct lp_fragment_shader_variant_key,
- sampler[nr_samplers]);
+ state[MAX2(nr_samplers, nr_sampler_views)]);
for (i = 0; i < shader->info.base.num_inputs; i++) {
shader->inputs[i].usage_mask = shader->info.base.input_usage_mask[i];
for(i = 0; i < key->nr_samplers; ++i) {
if(shader->info.base.file_mask[TGSI_FILE_SAMPLER] & (1 << i)) {
- lp_sampler_static_state(&key->sampler[i],
- lp->sampler_views[PIPE_SHADER_FRAGMENT][i],
- lp->samplers[PIPE_SHADER_FRAGMENT][i]);
+ lp_sampler_static_sampler_state(&key->state[i].sampler_state,
+ lp->samplers[PIPE_SHADER_FRAGMENT][i]);
+ }
+ }
+
+ /*
+ * XXX If TGSI_FILE_SAMPLER_VIEW exists assume all texture opcodes
+ * are dx10-style? Can't really have mixed opcodes, at least not
+ * if we want to skip the holes here (without rescanning tgsi).
+ */
+ if (shader->info.base.file_max[TGSI_FILE_SAMPLER_VIEW] != -1) {
+ key->nr_sampler_views = shader->info.base.file_max[TGSI_FILE_SAMPLER_VIEW] + 1;
+ for(i = 0; i < key->nr_sampler_views; ++i) {
+ if(shader->info.base.file_mask[TGSI_FILE_SAMPLER_VIEW] & (1 << i)) {
+ lp_sampler_static_texture_state(&key->state[i].texture_state,
+ lp->sampler_views[PIPE_SHADER_FRAGMENT][i]);
+ }
+ }
+ }
+ else {
+ key->nr_sampler_views = key->nr_samplers;
+ for(i = 0; i < key->nr_sampler_views; ++i) {
+ if(shader->info.base.file_mask[TGSI_FILE_SAMPLER] & (1 << i)) {
+ lp_sampler_static_texture_state(&key->state[i].texture_state,
+ lp->sampler_views[PIPE_SHADER_FRAGMENT][i]);
+ }
}
}
}
#define RAST_EDGE_TEST 1
+struct lp_sampler_static_state
+{
+ /*
+ * These attributes are effectively interleaved for more sane key handling.
+ * However, there might be lots of null space if the amount of samplers and
+ * textures isn't the same.
+ */
+ struct lp_static_sampler_state sampler_state;
+ struct lp_static_texture_state texture_state;
+};
+
+
struct lp_fragment_shader_variant_key
{
struct pipe_depth_state depth;
} alpha;
unsigned nr_cbufs:8;
- unsigned nr_samplers:8; /* actually derivable from just the shader */
+ unsigned nr_samplers:8; /* actually derivable from just the shader */
+ unsigned nr_sampler_views:8; /* actually derivable from just the shader */
unsigned flatshade:1;
unsigned occlusion_count:1;
enum pipe_format zsbuf_format;
enum pipe_format cbuf_format[PIPE_MAX_COLOR_BUFS];
- struct lp_sampler_static_state sampler[PIPE_MAX_SAMPLERS];
+ struct lp_sampler_static_state state[PIPE_MAX_SHADER_SAMPLER_VIEWS];
};
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
uint i;
- assert(num <= PIPE_MAX_SAMPLERS);
+ assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
assert(shader < PIPE_SHADER_TYPES);
assert(start + num <= Elements(llvmpipe->sampler_views[shader]));
uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS];
const void *addr;
- assert(num <= PIPE_MAX_SAMPLERS);
+ assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
if (!num)
return;
- for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
struct pipe_sampler_view *view = i < num ? views[i] : NULL;
if (view) {
#include "gallivm/lp_bld_tgsi.h"
#include "lp_jit.h"
#include "lp_tex_sample.h"
+#include "lp_state_fs.h"
#include "lp_debug.h"
LLVMValueRef ptr;
LLVMValueRef res;
- assert(unit < PIPE_MAX_SAMPLERS);
+ assert(unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
/* context[0] */
indices[0] = lp_build_const_int32(gallivm, 0);
LP_LLVM_TEXTURE_MEMBER(row_stride, LP_JIT_TEXTURE_ROW_STRIDE, FALSE)
LP_LLVM_TEXTURE_MEMBER(img_stride, LP_JIT_TEXTURE_IMG_STRIDE, FALSE)
LP_LLVM_TEXTURE_MEMBER(mip_offsets, LP_JIT_TEXTURE_MIP_OFFSETS, FALSE)
-LP_LLVM_TEXTURE_MEMBER(min_lod, LP_JIT_TEXTURE_MIN_LOD, TRUE)
-LP_LLVM_TEXTURE_MEMBER(max_lod, LP_JIT_TEXTURE_MAX_LOD, TRUE)
-LP_LLVM_TEXTURE_MEMBER(lod_bias, LP_JIT_TEXTURE_LOD_BIAS, TRUE)
-LP_LLVM_TEXTURE_MEMBER(border_color, LP_JIT_TEXTURE_BORDER_COLOR, FALSE)
+
+
+/**
+ * Fetch the specified member of the lp_jit_sampler 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
+lp_llvm_sampler_member(const struct lp_sampler_dynamic_state *base,
+ struct gallivm_state *gallivm,
+ unsigned unit,
+ unsigned member_index,
+ const char *member_name,
+ boolean emit_load)
+{
+ struct llvmpipe_sampler_dynamic_state *state =
+ (struct llvmpipe_sampler_dynamic_state *)base;
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef indices[4];
+ LLVMValueRef ptr;
+ LLVMValueRef res;
+
+ assert(unit < PIPE_MAX_SAMPLERS);
+
+ /* context[0] */
+ indices[0] = lp_build_const_int32(gallivm, 0);
+ /* context[0].samplers */
+ indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_SAMPLERS);
+ /* context[0].samplers[unit] */
+ indices[2] = lp_build_const_int32(gallivm, unit);
+ /* context[0].samplers[unit].member */
+ indices[3] = lp_build_const_int32(gallivm, member_index);
+
+ ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
+
+ if (emit_load)
+ res = LLVMBuildLoad(builder, ptr, "");
+ else
+ res = ptr;
+
+ lp_build_name(res, "context.sampler%u.%s", unit, member_name);
+
+ return res;
+}
+
+
+#define LP_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load) \
+ static LLVMValueRef \
+ lp_llvm_sampler_##_name( const struct lp_sampler_dynamic_state *base, \
+ struct gallivm_state *gallivm, \
+ unsigned unit) \
+ { \
+ return lp_llvm_sampler_member(base, gallivm, unit, _index, #_name, _emit_load ); \
+ }
+
+
+LP_LLVM_SAMPLER_MEMBER(min_lod, LP_JIT_SAMPLER_MIN_LOD, TRUE)
+LP_LLVM_SAMPLER_MEMBER(max_lod, LP_JIT_SAMPLER_MAX_LOD, TRUE)
+LP_LLVM_SAMPLER_MEMBER(lod_bias, LP_JIT_SAMPLER_LOD_BIAS, TRUE)
+LP_LLVM_SAMPLER_MEMBER(border_color, LP_JIT_SAMPLER_BORDER_COLOR, FALSE)
static void
struct gallivm_state *gallivm,
struct lp_type type,
boolean is_fetch,
- unsigned unit,
+ unsigned texture_index,
+ unsigned sampler_index,
const LLVMValueRef *coords,
const LLVMValueRef *offsets,
const struct lp_derivatives *derivs,
{
struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base;
- assert(unit < PIPE_MAX_SAMPLERS);
+ assert(sampler_index < PIPE_MAX_SAMPLERS);
+ assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
if (LP_PERF & PERF_NO_TEX) {
lp_build_sample_nop(gallivm, type, coords, texel);
}
lp_build_sample_soa(gallivm,
- &sampler->dynamic_state.static_state[unit],
+ &sampler->dynamic_state.static_state[texture_index].texture_state,
+ &sampler->dynamic_state.static_state[sampler_index].sampler_state,
&sampler->dynamic_state.base,
type,
is_fetch,
- unit,
+ texture_index,
+ sampler_index,
coords,
offsets,
derivs,
struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base;
assert(unit < PIPE_MAX_SAMPLERS);
-
+
lp_build_size_query_soa(gallivm,
- &sampler->dynamic_state.static_state[unit],
- &sampler->dynamic_state.base,
+ &sampler->dynamic_state.static_state[unit].texture_state,
+ &sampler->dynamic_state.base,
type,
- unit,
- explicit_lod,
- sizes_out);
+ unit,
+ explicit_lod,
+ sizes_out);
}
sampler->dynamic_state.base.row_stride = lp_llvm_texture_row_stride;
sampler->dynamic_state.base.img_stride = lp_llvm_texture_img_stride;
sampler->dynamic_state.base.mip_offsets = lp_llvm_texture_mip_offsets;
- sampler->dynamic_state.base.min_lod = lp_llvm_texture_min_lod;
- sampler->dynamic_state.base.max_lod = lp_llvm_texture_max_lod;
- sampler->dynamic_state.base.lod_bias = lp_llvm_texture_lod_bias;
- sampler->dynamic_state.base.border_color = lp_llvm_texture_border_color;
+ sampler->dynamic_state.base.min_lod = lp_llvm_sampler_min_lod;
+ sampler->dynamic_state.base.max_lod = lp_llvm_sampler_max_lod;
+ sampler->dynamic_state.base.lod_bias = lp_llvm_sampler_lod_bias;
+ sampler->dynamic_state.base.border_color = lp_llvm_sampler_border_color;
sampler->dynamic_state.static_state = static_state;
sampler->dynamic_state.context_ptr = context_ptr;