Commit 44307792 authored by Jesse Natalie's avatar Jesse Natalie Committed by Erik Faye-Lund

microsoft/compiler: Use non-deref image intrinsics for write/size

This is necessary to avoid having derefs with uniform mode, which
lower_explicit_io would turn into address computations.
parent 4666f8c9
......@@ -108,7 +108,7 @@ struct clc_image_lower_context
int metadata_index;
};
static nir_ssa_def *
static int
lower_image_deref_impl(nir_builder *b, struct clc_image_lower_context *context,
const struct glsl_type *new_var_type,
unsigned *num_bindings)
......@@ -123,13 +123,10 @@ lower_image_deref_impl(nir_builder *b, struct clc_image_lower_context *context,
image.buf_ids[context->num_buf_ids] = uniform->data.binding = (*num_bindings)++;
}
context->num_buf_ids++;
b->cursor = nir_after_instr(&context->deref->instr);
nir_deref_instr* deref_uniform = nir_build_deref_var(b, uniform);
return &deref_uniform->dest.ssa;
return uniform->data.binding;
}
static nir_ssa_def *
static int
lower_read_only_image_deref(nir_builder *b, struct clc_image_lower_context *context,
nir_alu_type image_type)
{
......@@ -144,7 +141,7 @@ lower_read_only_image_deref(nir_builder *b, struct clc_image_lower_context *cont
return lower_image_deref_impl(b, context, new_var_type, context->num_srvs);
}
static nir_ssa_def *
static int
lower_read_write_image_deref(nir_builder *b, struct clc_image_lower_context *context,
nir_alu_type image_type)
{
......@@ -182,7 +179,7 @@ clc_lower_input_image_deref(nir_builder *b, struct clc_image_lower_context *cont
IMAGE_UNIFORM_TYPE_COUNT
};
nir_ssa_def *uniform_deref_dests[IMAGE_UNIFORM_TYPE_COUNT] = {0};
int image_bindings[IMAGE_UNIFORM_TYPE_COUNT] = {-1, -1, -1};
nir_ssa_def *format_deref_dest = NULL, *order_deref_dest = NULL;
nir_variable *in_var = nir_deref_instr_get_variable(context->deref);
......@@ -214,16 +211,15 @@ clc_lower_input_image_deref(nir_builder *b, struct clc_image_lower_context *cont
default: unreachable("Unsupported image type for load.");
}
nir_ssa_def *image_deref = uniform_deref_dests[type];
if (!image_deref) {
const struct glsl_type *new_var_type;
int image_binding = image_bindings[type];
if (image_binding < 0) {
if (in_var->data.access & ACCESS_NON_WRITEABLE) {
image_deref = lower_read_only_image_deref(b, context, dest_type);
image_binding = lower_read_only_image_deref(b, context, dest_type);
} else {
image_deref = lower_read_write_image_deref(b, context, dest_type);
image_binding = lower_read_write_image_deref(b, context, dest_type);
}
uniform_deref_dests[type] = image_deref;
image_bindings[type] = image_binding;
}
if (in_var->data.access & ACCESS_NON_WRITEABLE) {
......@@ -235,19 +231,18 @@ clc_lower_input_image_deref(nir_builder *b, struct clc_image_lower_context *cont
unsigned coord_comps = glsl_get_sampler_coordinate_components(deref->type);
nir_ssa_def *coord =
nir_channels(b, intrinsic->src[1].ssa, (1 << coord_comps) - 1);
nir_tex_instr *tex = nir_tex_instr_create(b->shader, 3);
nir_tex_instr *tex = nir_tex_instr_create(b->shader, 2);
tex->op = nir_texop_txf;
tex->is_array = glsl_sampler_type_is_array(in_var->type);
tex->sampler_dim = glsl_get_sampler_dim(in_var->type);
tex->src[0].src = nir_src_for_ssa(image_deref);
tex->src[0].src_type = nir_tex_src_texture_deref;
tex->src[1].src = nir_src_for_ssa(coord);
tex->src[1].src_type = nir_tex_src_coord;
tex->src[2].src = nir_src_for_ssa(nir_imm_int(b, 0));
tex->src[2].src_type = nir_tex_src_lod;
tex->coord_components = tex->src[1].src.ssa->num_components;
tex->src[0].src = nir_src_for_ssa(coord);
tex->src[0].src_type = nir_tex_src_coord;
tex->src[1].src = nir_src_for_ssa(nir_imm_int(b, 0));
tex->src[1].src_type = nir_tex_src_lod;
tex->coord_components = tex->src[0].src.ssa->num_components;
tex->dest_type = dest_type;
tex->texture_index = image_binding;
nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL);
nir_builder_instr_insert(b, &tex->instr);
......@@ -255,49 +250,46 @@ clc_lower_input_image_deref(nir_builder *b, struct clc_image_lower_context *cont
nir_instr_remove(&intrinsic->instr);
} else {
// Op on a writable image, leave as image intrinsic
nir_src uniform_src = nir_src_for_ssa(image_deref);
nir_instr_rewrite_src(&intrinsic->instr, src, uniform_src);
nir_rewrite_image_intrinsic(intrinsic, nir_imm_int(b, image_binding), false);
}
break;
}
case nir_intrinsic_image_deref_size: {
nir_ssa_def *image_deref = NULL;
int image_binding = -1;
for (unsigned i = 0; i < IMAGE_UNIFORM_TYPE_COUNT; ++i) {
if (uniform_deref_dests[i]) {
image_deref = uniform_deref_dests[i];
if (image_bindings[i] >= 0) {
image_binding = image_bindings[i];
break;
}
}
if (!image_deref) {
if (image_binding < 0) {
// Skip for now and come back to it
if (pass == 0)
break;
type = FLOAT4;
const struct glsl_type *new_var_type;
if (in_var->data.access & ACCESS_NON_WRITEABLE) {
image_deref = lower_read_only_image_deref(b, context, nir_type_float32);
image_binding = lower_read_only_image_deref(b, context, nir_type_float32);
} else {
image_deref = lower_read_write_image_deref(b, context, nir_type_float32);
image_binding = lower_read_write_image_deref(b, context, nir_type_float32);
}
uniform_deref_dests[type] = image_deref;
image_bindings[type] = image_binding;
}
if (in_var->data.access & ACCESS_NON_WRITEABLE) {
// Size query on non-readable resource, convert to txs
b->cursor = nir_before_instr(&intrinsic->instr);
unsigned num_src = 2;
unsigned num_src = 1;
nir_tex_instr *tex = nir_tex_instr_create(b->shader, num_src);
tex->op = nir_texop_txs;
tex->is_array = glsl_sampler_type_is_array(in_var->type);
tex->sampler_dim = glsl_get_sampler_dim(in_var->type);
tex->src[0].src = nir_src_for_ssa(image_deref);
tex->src[0].src_type = nir_tex_src_texture_deref;
tex->src[1].src = nir_src_for_ssa(intrinsic->src[1].ssa);
tex->src[1].src_type = nir_tex_src_lod;
tex->texture_index = image_binding;
tex->src[0].src = nir_src_for_ssa(intrinsic->src[1].ssa);
tex->src[0].src_type = nir_tex_src_lod;
tex->dest_type = nir_type_uint;
nir_ssa_dest_init(&tex->instr, &tex->dest, nir_tex_instr_dest_size(tex), 32, NULL);
......@@ -306,8 +298,7 @@ clc_lower_input_image_deref(nir_builder *b, struct clc_image_lower_context *cont
nir_instr_remove(&intrinsic->instr);
} else {
// Op on a writable image, leave as image intrinsic
nir_src uniform_src = nir_src_for_ssa(image_deref);
nir_instr_rewrite_src(&intrinsic->instr, src, uniform_src);
nir_rewrite_image_intrinsic(intrinsic, nir_imm_int(b, image_binding), false);
}
break;
}
......@@ -317,7 +308,7 @@ clc_lower_input_image_deref(nir_builder *b, struct clc_image_lower_context *cont
nir_ssa_def **cached_deref = intrinsic->intrinsic == nir_intrinsic_image_deref_format ?
&format_deref_dest : &order_deref_dest;
if (!*cached_deref) {
nir_variable *new_input = nir_variable_create(b->shader, nir_var_shader_in, glsl_uint_type(), NULL);
nir_variable *new_input = nir_variable_create(b->shader, nir_var_uniform, glsl_uint_type(), NULL);
new_input->data.driver_location = in_var->data.driver_location;
if (intrinsic->intrinsic == nir_intrinsic_image_deref_format) {
/* Match cl_image_format { image_channel_order, image_channel_data_type }; */
......@@ -348,14 +339,14 @@ clc_lower_input_image_deref(nir_builder *b, struct clc_image_lower_context *cont
default: unreachable("Unsupported image format for sample.");
}
nir_ssa_def *image_deref = uniform_deref_dests[type];
if (!image_deref) {
image_deref = uniform_deref_dests[type] =
int image_binding = image_bindings[type];
if (image_binding < 0) {
image_binding = image_bindings[type] =
lower_read_only_image_deref(b, context, tex->dest_type);
}
nir_src uniform_src = nir_src_for_ssa(image_deref);
nir_instr_rewrite_src(&tex->instr, src, uniform_src);
nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_texture_deref));
tex->texture_index = image_binding;
}
}
}
......
......@@ -2868,13 +2868,11 @@ emit_end_primitive(struct ntd_context *ctx, nir_intrinsic_instr *intr)
}
static bool
emit_image_deref_store(struct ntd_context *ctx, nir_intrinsic_instr *intr)
emit_image_store(struct ntd_context *ctx, nir_intrinsic_instr *intr)
{
assert(intr->src[0].is_ssa);
nir_deref_instr *deref = nir_instr_as_deref(intr->src[0].ssa->parent_instr);
nir_variable *var = nir_deref_instr_get_variable(deref);
int binding = nir_src_as_int(intr->src[0]);
const struct dxil_value *handle = ctx->uav_handles[var->data.binding];
const struct dxil_value *handle = ctx->uav_handles[binding];
if (!handle)
return false;
......@@ -2883,7 +2881,8 @@ emit_image_deref_store(struct ntd_context *ctx, nir_intrinsic_instr *intr)
return false;
const struct dxil_value *coord[3] = { int32_undef, int32_undef, int32_undef };
unsigned num_coords = glsl_get_sampler_coordinate_components(var->type);
enum glsl_sampler_dim image_dim = nir_intrinsic_image_dim(intr);
unsigned num_coords = glsl_get_sampler_dim_coordinate_components(image_dim);
assert(num_coords <= nir_src_num_components(intr->src[1]));
for (unsigned i = 0; i < num_coords; ++i) {
coord[i] = get_src(ctx, &intr->src[1], i, nir_type_uint);
......@@ -2891,7 +2890,7 @@ emit_image_deref_store(struct ntd_context *ctx, nir_intrinsic_instr *intr)
return false;
}
nir_alu_type in_type = nir_get_nir_type_for_glsl_base_type(glsl_get_sampler_result_type(var->type));
nir_alu_type in_type = nir_intrinsic_type(intr);
enum overload_type overload = get_overload(in_type, 32);
assert(nir_src_bit_size(intr->src[3]) == 32);
......@@ -2912,11 +2911,10 @@ emit_image_deref_store(struct ntd_context *ctx, nir_intrinsic_instr *intr)
if (!write_mask)
return false;
if (glsl_get_sampler_dim(var->type) == GLSL_SAMPLER_DIM_BUF) {
if (image_dim == GLSL_SAMPLER_DIM_BUF) {
coord[1] = int32_undef;
return emit_bufferstore_call(ctx, handle, coord, value, write_mask, overload);
}
else
} else
return emit_texturestore_call(ctx, handle, coord, value, write_mask, overload);
}
......@@ -2946,13 +2944,11 @@ emit_texture_size(struct ntd_context *ctx, struct texop_parameters *params)
}
static bool
emit_image_deref_size(struct ntd_context *ctx, nir_intrinsic_instr *intr)
emit_image_size(struct ntd_context *ctx, nir_intrinsic_instr *intr)
{
assert(intr->src[0].is_ssa);
nir_deref_instr *deref = nir_instr_as_deref(intr->src[0].ssa->parent_instr);
nir_variable *var = nir_deref_instr_get_variable(deref);
int binding = nir_src_as_int(intr->src[0]);
const struct dxil_value *handle = ctx->uav_handles[var->data.binding];
const struct dxil_value *handle = ctx->uav_handles[binding];
if (!handle)
return false;
......@@ -3224,10 +3220,10 @@ emit_intrinsic(struct ntd_context *ctx, nir_intrinsic_instr *intr)
return emit_shared_atomic(ctx, intr, DXIL_RMWOP_XCHG, nir_type_int);
case nir_intrinsic_shared_atomic_comp_swap_dxil:
return emit_shared_atomic_comp_swap(ctx, intr);
case nir_intrinsic_image_deref_store:
return emit_image_deref_store(ctx, intr);
case nir_intrinsic_image_deref_size:
return emit_image_deref_size(ctx, intr);
case nir_intrinsic_image_store:
return emit_image_store(ctx, intr);
case nir_intrinsic_image_size:
return emit_image_size(ctx, intr);
case nir_intrinsic_load_num_work_groups:
case nir_intrinsic_load_local_group_size:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment