#endif
}
+void
+draw_set_images(struct draw_context *draw,
+ enum pipe_shader_type shader_stage,
+ struct pipe_image_view *views,
+ unsigned num)
+{
+ unsigned i;
+
+ debug_assert(shader_stage < PIPE_SHADER_TYPES);
+ debug_assert(num <= PIPE_MAX_SHADER_IMAGES);
+
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+
+ for (i = 0; i < num; ++i)
+ draw->images[shader_stage][i] = &views[i];
+ for (i = num; i < draw->num_sampler_views[shader_stage]; ++i)
+ draw->images[shader_stage][i] = NULL;
+
+ draw->num_images[shader_stage] = num;
+}
+
void
draw_set_mapped_texture(struct draw_context *draw,
enum pipe_shader_type shader_stage,
#endif
}
+void
+draw_set_mapped_image(struct draw_context *draw,
+ enum pipe_shader_type shader_stage,
+ unsigned idx,
+ uint32_t width, uint32_t height, uint32_t depth,
+ const void *base_ptr,
+ uint32_t row_stride,
+ uint32_t img_stride)
+{
+#ifdef HAVE_LLVM
+ if (draw->llvm)
+ draw_llvm_set_mapped_image(draw,
+ shader_stage,
+ idx,
+ width, height, depth,
+ base_ptr,
+ row_stride, img_stride);
+#endif
+}
+
/**
* XXX: Results for PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS because there are two
* different ways of setting textures, and drivers typically only support one.
struct pipe_sampler_state **samplers,
unsigned num);
+void
+draw_set_images(struct draw_context *draw,
+ enum pipe_shader_type shader_stage,
+ struct pipe_image_view *images,
+ unsigned num);
+
void
draw_set_mapped_texture(struct draw_context *draw,
enum pipe_shader_type shader_stage,
uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS],
uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS]);
+void
+draw_set_mapped_image(struct draw_context *draw,
+ enum pipe_shader_type shader_stage,
+ unsigned idx,
+ uint32_t width, uint32_t height, uint32_t depth,
+ const void *base_ptr,
+ uint32_t row_stride,
+ uint32_t img_stride);
/*
* Vertex shader functions
llvm_gs->variant_key_size =
draw_gs_llvm_variant_key_size(
MAX2(gs->info.file_max[TGSI_FILE_SAMPLER]+1,
- gs->info.file_max[TGSI_FILE_SAMPLER_VIEW]+1));
+ gs->info.file_max[TGSI_FILE_SAMPLER_VIEW]+1),
+ gs->info.file_max[TGSI_FILE_IMAGE]+1);
} else
#endif
{
const struct lp_bld_tgsi_system_values *system_values,
LLVMValueRef context_ptr,
const struct lp_build_sampler_soa *draw_sampler,
+ const struct lp_build_image_soa *draw_image,
boolean clamp_vertex_color,
struct lp_build_mask_context *bld_mask)
{
params.info = &llvm->draw->vs.vertex_shader->info;
params.ssbo_ptr = ssbos_ptr;
params.ssbo_sizes_ptr = num_ssbos_ptr;
+ params.image = draw_image;
lp_build_tgsi_soa(variant->gallivm,
tokens,
const int vector_length = lp_native_vector_width / 32;
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][TGSI_NUM_CHANNELS];
struct lp_build_sampler_soa *sampler = 0;
+ struct lp_build_image_soa *image = NULL;
LLVMValueRef ret, clipmask_bool_ptr;
struct draw_llvm_variant_key *key = &variant->key;
/* If geometry shader is present we need to skip both the viewport
/* code generated texture sampling */
sampler = draw_llvm_sampler_soa_create(draw_llvm_variant_key_samplers(key));
+ image = draw_llvm_image_soa_create(draw_llvm_variant_key_images(key));
+
step = lp_build_const_int32(gallivm, vector_length);
ind_vec = blduivec.undef;
&system_values,
context_ptr,
sampler,
+ image,
key->clamp_vertex_color,
&mask);
lp_build_loop_end_cond(&lp_loop, count, step, LLVMIntUGE);
sampler->destroy(sampler);
+ image->destroy(image);
/* return clipping boolean value for function */
ret = clipmask_booli8(gallivm, vs_type, clipmask_bool_ptr,
unsigned i;
struct draw_llvm_variant_key *key;
struct draw_sampler_static_state *draw_sampler;
+ struct draw_image_static_state *draw_image;
key = (struct draw_llvm_variant_key *)store;
key->nr_sampler_views = key->nr_samplers;
}
+ key->nr_images = llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_IMAGE] + 1;
+
/* Presumably all variants of the shader should have the same
* number of vertex elements - ie the number of shader inputs.
* NOTE: we NEED to store the needed number of needed inputs
llvm->draw->sampler_views[PIPE_SHADER_VERTEX][i]);
}
+ draw_image = draw_llvm_variant_key_images(key);
+ memset(draw_image, 0,
+ key->nr_images * sizeof *draw_image);
+ for (i = 0; i < key->nr_images; i++) {
+ lp_sampler_static_texture_state_image(&draw_image[i].image_state,
+ llvm->draw->images[PIPE_SHADER_VERTEX][i]);
+ }
return key;
}
{
unsigned i;
struct draw_sampler_static_state *sampler = draw_llvm_variant_key_samplers(key);
-
+ struct draw_image_static_state *image = draw_llvm_variant_key_images(key);
debug_printf("clamp_vertex_color = %u\n", key->clamp_vertex_color);
debug_printf("clip_xy = %u\n", key->clip_xy);
debug_printf("clip_z = %u\n", key->clip_z);
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));
}
+
+ for (i = 0 ; i < key->nr_images; i++)
+ debug_printf("images[%i].format = %s\n", i, util_format_name(image[i].image_state.format));
}
}
}
+void
+draw_llvm_set_mapped_image(struct draw_context *draw,
+ enum pipe_shader_type shader_stage,
+ unsigned idx,
+ uint32_t width, uint32_t height, uint32_t depth,
+ const void *base_ptr,
+ uint32_t row_stride,
+ uint32_t img_stride)
+{
+ struct draw_jit_image *jit_image;
+
+ assert(shader_stage == PIPE_SHADER_VERTEX ||
+ shader_stage == PIPE_SHADER_GEOMETRY);
+
+ if (shader_stage == PIPE_SHADER_VERTEX) {
+ assert(idx < ARRAY_SIZE(draw->llvm->jit_context.images));
+
+ jit_image = &draw->llvm->jit_context.images[idx];
+ } else if (shader_stage == PIPE_SHADER_GEOMETRY) {
+ assert(idx < ARRAY_SIZE(draw->llvm->gs_jit_context.images));
+
+ jit_image = &draw->llvm->gs_jit_context.images[idx];
+ } else {
+ assert(0);
+ return;
+ }
+
+ jit_image->width = width;
+ jit_image->height = height;
+ jit_image->depth = depth;
+ jit_image->base = base_ptr;
+
+ jit_image->row_stride = row_stride;
+ jit_image->img_stride = img_stride;
+}
+
void
draw_llvm_set_sampler_state(struct draw_context *draw,
LLVMBuilderRef builder;
LLVMValueRef io_ptr, input_array, num_prims, mask_val;
struct lp_build_sampler_soa *sampler = 0;
+ struct lp_build_image_soa *image = NULL;
struct lp_build_context bld;
struct lp_bld_tgsi_system_values system_values;
char func_name[64];
/* code generated texture sampling */
sampler = draw_llvm_sampler_soa_create(variant->key.samplers);
-
+ image = draw_llvm_image_soa_create(draw_gs_llvm_variant_key_images(&variant->key));
mask_val = generate_mask_value(variant, gs_type);
lp_build_mask_begin(&mask, gallivm, gs_type, mask_val);
params.gs_iface = (const struct lp_build_tgsi_gs_iface *)&gs_iface;
params.ssbo_ptr = ssbos_ptr;
params.ssbo_sizes_ptr = num_ssbos_ptr;
+ params.image = image;
lp_build_tgsi_soa(variant->gallivm,
tokens,
outputs);
sampler->destroy(sampler);
+ image->destroy(image);
lp_build_mask_end(&mask);
unsigned i;
struct draw_gs_llvm_variant_key *key;
struct draw_sampler_static_state *draw_sampler;
+ struct draw_image_static_state *draw_image;
key = (struct draw_gs_llvm_variant_key *)store;
key->nr_sampler_views = key->nr_samplers;
}
+ key->nr_images = llvm->draw->gs.geometry_shader->info.file_max[TGSI_FILE_IMAGE] + 1;
+
draw_sampler = key->samplers;
memset(draw_sampler, 0, MAX2(key->nr_samplers, key->nr_sampler_views) * sizeof *draw_sampler);
llvm->draw->sampler_views[PIPE_SHADER_GEOMETRY][i]);
}
+ draw_image = draw_gs_llvm_variant_key_images(key);
+ memset(draw_image, 0,
+ key->nr_images * sizeof *draw_image);
+ for (i = 0; i < key->nr_images; i++) {
+ lp_sampler_static_texture_state_image(&draw_image[i].image_state,
+ llvm->draw->images[PIPE_SHADER_GEOMETRY][i]);
+ }
return key;
}
{
unsigned i;
struct draw_sampler_static_state *sampler = key->samplers;
-
+ struct draw_image_static_state *image = draw_gs_llvm_variant_key_images(key);
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));
}
+
+ for (i = 0 ; i < key->nr_images; i++)
+ debug_printf("images[%i].format = %s\n", i, util_format_name(image[i].image_state.format));
+
}
struct lp_static_texture_state texture_state;
};
+struct draw_image_static_state
+{
+ struct lp_static_texture_state image_state;
+};
+
struct draw_jit_sampler
{
unsigned nr_vertex_elements:8;
unsigned nr_samplers:8;
unsigned nr_sampler_views:8;
+ unsigned nr_images:8;
unsigned clamp_vertex_color:1;
unsigned clip_xy:1;
unsigned clip_z:1;
/* Followed by variable number of samplers:
*/
/* struct draw_sampler_static_state sampler; */
+ /* Followed by variable number of images
+ */
};
struct draw_gs_llvm_variant_key
{
unsigned nr_samplers:8;
unsigned nr_sampler_views:8;
+ unsigned nr_images:8;
unsigned num_outputs:8;
/* note padding here - must use memset */
struct draw_sampler_static_state samplers[1];
+ /* Followed by variable number of images.*/
};
#define DRAW_LLVM_MAX_VARIANT_KEY_SIZE \
(sizeof(struct draw_llvm_variant_key) + \
PIPE_MAX_SHADER_SAMPLER_VIEWS * sizeof(struct draw_sampler_static_state) + \
+ PIPE_MAX_SHADER_IMAGES * sizeof(struct draw_image_static_state) + \
(PIPE_MAX_ATTRIBS-1) * sizeof(struct pipe_vertex_element))
#define DRAW_GS_LLVM_MAX_VARIANT_KEY_SIZE \
(sizeof(struct draw_gs_llvm_variant_key) + \
+ PIPE_MAX_SHADER_IMAGES * sizeof(struct draw_image_static_state) + \
PIPE_MAX_SHADER_SAMPLER_VIEWS * sizeof(struct draw_sampler_static_state))
static inline size_t
draw_llvm_variant_key_size(unsigned nr_vertex_elements,
- unsigned nr_samplers)
+ unsigned nr_samplers, unsigned nr_images)
{
return (sizeof(struct draw_llvm_variant_key) +
nr_samplers * sizeof(struct draw_sampler_static_state) +
+ nr_images * sizeof(struct draw_image_static_state) +
(nr_vertex_elements - 1) * sizeof(struct pipe_vertex_element));
}
static inline size_t
-draw_gs_llvm_variant_key_size(unsigned nr_samplers)
+draw_gs_llvm_variant_key_size(unsigned nr_samplers, unsigned nr_images)
{
return (sizeof(struct draw_gs_llvm_variant_key) +
+ (nr_images) * sizeof(struct draw_sampler_static_state) +
(nr_samplers - 1) * sizeof(struct draw_sampler_static_state));
}
&key->vertex_element[key->nr_vertex_elements];
}
+static inline struct draw_image_static_state *
+draw_llvm_variant_key_images(struct draw_llvm_variant_key *key)
+{
+ struct draw_sampler_static_state *samplers = (struct draw_sampler_static_state *)
+ (&key->vertex_element[key->nr_vertex_elements]);
+ return (struct draw_image_static_state *)
+ &samplers[key->nr_samplers];
+}
+
+static inline struct draw_image_static_state *
+draw_gs_llvm_variant_key_images(struct draw_gs_llvm_variant_key *key)
+{
+ return (struct draw_image_static_state *)
+ &key->samplers[key->nr_samplers];
+}
struct draw_llvm_variant_list_item
{
struct lp_build_sampler_soa *
draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state);
+struct lp_build_image_soa *
+draw_llvm_image_soa_create(const struct draw_image_static_state *static_state);
+
void
draw_llvm_set_sampler_state(struct draw_context *draw,
enum pipe_shader_type shader_stage);
uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS],
uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS]);
+void
+draw_llvm_set_mapped_image(struct draw_context *draw,
+ enum pipe_shader_type shader_stage,
+ unsigned idx,
+ uint32_t width, uint32_t height, uint32_t depth,
+ const void *base_ptr,
+ uint32_t row_stride,
+ uint32_t img_stride);
#endif
struct draw_llvm_sampler_dynamic_state dynamic_state;
};
+struct draw_llvm_image_dynamic_state
+{
+ struct lp_sampler_dynamic_state base;
+
+ const struct draw_image_static_state *static_state;
+};
+
+struct draw_llvm_image_soa
+{
+ struct lp_build_image_soa base;
+
+ struct draw_llvm_image_dynamic_state dynamic_state;
+};
/**
* Fetch the specified member of the lp_jit_texture structure.
return res;
}
+/**
+ * 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_image_member(const struct lp_sampler_dynamic_state *base,
+ struct gallivm_state *gallivm,
+ LLVMValueRef context_ptr,
+ unsigned image_unit,
+ unsigned member_index,
+ const char *member_name,
+ boolean emit_load)
+{
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef indices[4];
+ LLVMValueRef ptr;
+ LLVMValueRef res;
+
+ debug_assert(image_unit < PIPE_MAX_SHADER_IMAGES);
+
+ /* context[0] */
+ indices[0] = lp_build_const_int32(gallivm, 0);
+ /* context[0].textures */
+ indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_IMAGES);
+ /* context[0].textures[unit] */
+ indices[2] = lp_build_const_int32(gallivm, image_unit);
+ /* context[0].textures[unit].member */
+ indices[3] = lp_build_const_int32(gallivm, member_index);
+
+ ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");
+
+ if (emit_load)
+ res = LLVMBuildLoad(builder, ptr, "");
+ else
+ res = ptr;
+
+ lp_build_name(res, "context.image%u.%s", image_unit, member_name);
+
+ return res;
+}
/**
* Helper macro to instantiate the functions that generate the code to
DRAW_LLVM_SAMPLER_MEMBER(lod_bias, DRAW_JIT_SAMPLER_LOD_BIAS, TRUE)
DRAW_LLVM_SAMPLER_MEMBER(border_color, DRAW_JIT_SAMPLER_BORDER_COLOR, FALSE)
+#define DRAW_LLVM_IMAGE_MEMBER(_name, _index, _emit_load) \
+ static LLVMValueRef \
+ draw_llvm_image_##_name( const struct lp_sampler_dynamic_state *base, \
+ struct gallivm_state *gallivm, \
+ LLVMValueRef context_ptr, \
+ unsigned image_unit) \
+ { \
+ return draw_llvm_image_member(base, gallivm, context_ptr, \
+ image_unit, _index, #_name, _emit_load ); \
+ }
+
+
+DRAW_LLVM_IMAGE_MEMBER(width, DRAW_JIT_IMAGE_WIDTH, TRUE)
+DRAW_LLVM_IMAGE_MEMBER(height, DRAW_JIT_IMAGE_HEIGHT, TRUE)
+DRAW_LLVM_IMAGE_MEMBER(depth, DRAW_JIT_IMAGE_DEPTH, TRUE)
+DRAW_LLVM_IMAGE_MEMBER(base_ptr, DRAW_JIT_IMAGE_BASE, TRUE)
+DRAW_LLVM_IMAGE_MEMBER(row_stride, DRAW_JIT_IMAGE_ROW_STRIDE, TRUE)
+DRAW_LLVM_IMAGE_MEMBER(img_stride, DRAW_JIT_IMAGE_IMG_STRIDE, TRUE)
static void
draw_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
return &sampler->base;
}
+static void
+draw_llvm_image_soa_emit_op(const struct lp_build_image_soa *base,
+ struct gallivm_state *gallivm,
+ const struct lp_img_params *params)
+{
+ struct draw_llvm_image_soa *image = (struct draw_llvm_image_soa *)base;
+ unsigned image_index = params->image_index;
+ assert(image_index < PIPE_MAX_SHADER_IMAGES);
+
+ lp_build_img_op_soa(&image->dynamic_state.static_state[image_index].image_state,
+ &image->dynamic_state.base,
+ gallivm, params);
+}
+/**
+ * Fetch the texture size.
+ */
+static void
+draw_llvm_image_soa_emit_size_query(const struct lp_build_image_soa *base,
+ struct gallivm_state *gallivm,
+ const struct lp_sampler_size_query_params *params)
+{
+ struct draw_llvm_image_soa *image = (struct draw_llvm_image_soa *)base;
+
+ assert(params->texture_unit < PIPE_MAX_SHADER_IMAGES);
+
+ lp_build_size_query_soa(gallivm,
+ &image->dynamic_state.static_state[params->texture_unit].image_state,
+ &image->dynamic_state.base,
+ params);
+}
+static void
+draw_llvm_image_soa_destroy(struct lp_build_image_soa *image)
+{
+ FREE(image);
+}
+
+struct lp_build_image_soa *
+draw_llvm_image_soa_create(const struct draw_image_static_state *static_state)
+{
+ struct draw_llvm_image_soa *image;
+
+ image = CALLOC_STRUCT(draw_llvm_image_soa);
+ if (!image)
+ return NULL;
+
+ image->base.destroy = draw_llvm_image_soa_destroy;
+ image->base.emit_op = draw_llvm_image_soa_emit_op;
+ image->base.emit_size_query = draw_llvm_image_soa_emit_size_query;
+
+ image->dynamic_state.base.width = draw_llvm_image_width;
+ image->dynamic_state.base.height = draw_llvm_image_height;
+
+ image->dynamic_state.base.depth = draw_llvm_image_depth;
+ image->dynamic_state.base.base_ptr = draw_llvm_image_base_ptr;
+ image->dynamic_state.base.row_stride = draw_llvm_image_row_stride;
+ image->dynamic_state.base.img_stride = draw_llvm_image_img_stride;
+
+ image->dynamic_state.static_state = static_state;
+
+ return &image->base;
+}
const struct pipe_sampler_state *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
unsigned num_samplers[PIPE_SHADER_TYPES];
+ struct pipe_image_view *images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES];
+ unsigned num_images[PIPE_SHADER_TYPES];
+
struct pipe_query_data_pipeline_statistics statistics;
boolean collect_statistics;
draw_llvm_variant_key_size(
vs->base.info.file_max[TGSI_FILE_INPUT]+1,
MAX2(vs->base.info.file_max[TGSI_FILE_SAMPLER]+1,
- vs->base.info.file_max[TGSI_FILE_SAMPLER_VIEW]+1));
+ vs->base.info.file_max[TGSI_FILE_SAMPLER_VIEW]+1),
+ vs->base.info.file_max[TGSI_FILE_IMAGE]+1);
vs->base.state.stream_output = state->stream_output;
vs->base.draw = draw;