draw: add vs/gs images support

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
This commit is contained in:
Dave Airlie 2019-07-20 14:26:48 +10:00
parent ceb8d0ac5a
commit dc2357070c
8 changed files with 316 additions and 7 deletions

View File

@ -1033,6 +1033,27 @@ draw_set_samplers(struct draw_context *draw,
#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,
@ -1055,6 +1076,26 @@ draw_set_mapped_texture(struct draw_context *draw,
#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.

View File

@ -176,6 +176,12 @@ draw_set_samplers(struct draw_context *draw,
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,
@ -187,6 +193,14 @@ draw_set_mapped_texture(struct draw_context *draw,
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

View File

@ -883,7 +883,8 @@ draw_create_geometry_shader(struct draw_context *draw,
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
{

View File

@ -681,6 +681,7 @@ generate_vs(struct draw_llvm_variant *variant,
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)
{
@ -709,6 +710,7 @@ generate_vs(struct draw_llvm_variant *variant,
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,
@ -1635,6 +1637,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
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
@ -1750,6 +1753,8 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
/* 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;
@ -1994,6 +1999,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
&system_values,
context_ptr,
sampler,
image,
key->clamp_vertex_color,
&mask);
@ -2040,6 +2046,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
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,
@ -2057,6 +2064,7 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
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;
@ -2089,6 +2097,8 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm, char *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
@ -2127,6 +2137,13 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
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;
}
@ -2136,7 +2153,7 @@ draw_llvm_dump_variant_key(struct draw_llvm_variant_key *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);
@ -2157,6 +2174,9 @@ draw_llvm_dump_variant_key(struct draw_llvm_variant_key *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));
}
@ -2204,6 +2224,42 @@ draw_llvm_set_mapped_texture(struct draw_context *draw,
}
}
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,
@ -2331,6 +2387,7 @@ draw_gs_llvm_generate(struct draw_llvm *llvm,
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];
@ -2427,7 +2484,7 @@ draw_gs_llvm_generate(struct draw_llvm *llvm,
/* 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);
@ -2454,6 +2511,7 @@ draw_gs_llvm_generate(struct draw_llvm *llvm,
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,
@ -2461,6 +2519,7 @@ draw_gs_llvm_generate(struct draw_llvm *llvm,
outputs);
sampler->destroy(sampler);
image->destroy(image);
lp_build_mask_end(&mask);
@ -2545,6 +2604,7 @@ draw_gs_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
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;
@ -2565,6 +2625,8 @@ draw_gs_llvm_make_variant_key(struct draw_llvm *llvm, char *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);
@ -2578,6 +2640,13 @@ draw_gs_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
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;
}
@ -2586,9 +2655,13 @@ draw_gs_llvm_dump_variant_key(struct draw_gs_llvm_variant_key *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));
}

View File

@ -69,6 +69,11 @@ struct draw_sampler_static_state
struct lp_static_texture_state texture_state;
};
struct draw_image_static_state
{
struct lp_static_texture_state image_state;
};
struct draw_jit_sampler
{
@ -340,6 +345,7 @@ struct draw_llvm_variant_key
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;
@ -359,42 +365,50 @@ struct draw_llvm_variant_key
/* 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));
}
@ -406,6 +420,21 @@ draw_llvm_variant_key_samplers(struct draw_llvm_variant_key *key)
&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
{
@ -558,6 +587,9 @@ draw_gs_llvm_dump_variant_key(struct draw_gs_llvm_variant_key *key);
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);
@ -573,4 +605,12 @@ draw_llvm_set_mapped_texture(struct draw_context *draw,
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

View File

@ -72,6 +72,19 @@ struct draw_llvm_sampler_soa
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.
@ -164,6 +177,50 @@ draw_llvm_sampler_member(const struct lp_sampler_dynamic_state *base,
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
@ -214,6 +271,24 @@ 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)
#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)
@ -293,3 +368,64 @@ draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_stat
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;
}

View File

@ -342,6 +342,9 @@ struct draw_context
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;

View File

@ -103,7 +103,8 @@ draw_create_vs_llvm(struct draw_context *draw,
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;