From 63fe4888ea2af15827e52c292f07fb26069c94a9 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Wed, 29 Dec 2021 09:59:33 -0800 Subject: [PATCH] d3d12: Lower cube images to 2D arrays via existing int cubemap lowering pass Note that the coordinates are not lowered, just types. Reviewed-by: Sil Vilerino Part-of: --- .../d3d12/d3d12_lower_int_cubemap_to_array.c | 251 ++++++++++++++++----- 1 file changed, 190 insertions(+), 61 deletions(-) diff --git a/src/gallium/drivers/d3d12/d3d12_lower_int_cubemap_to_array.c b/src/gallium/drivers/d3d12/d3d12_lower_int_cubemap_to_array.c index 630da4f..819dc51 100644 --- a/src/gallium/drivers/d3d12/d3d12_lower_int_cubemap_to_array.c +++ b/src/gallium/drivers/d3d12/d3d12_lower_int_cubemap_to_array.c @@ -27,38 +27,99 @@ #include "nir_builtin_builder.h" static bool -lower_int_cubmap_to_array_filter(const nir_instr *instr, - UNUSED const void *_options) +type_needs_lowering(const struct glsl_type *type) { - if (instr->type != nir_instr_type_tex) + type = glsl_without_array(type); + if (!glsl_type_is_image(type) && !glsl_type_is_sampler(type)) return false; - - nir_tex_instr *tex = nir_instr_as_tex(instr); - - if (tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE) + if (glsl_get_sampler_dim(type) != GLSL_SAMPLER_DIM_CUBE) return false; + if (glsl_type_is_image(type)) + return true; + return glsl_base_type_is_integer(glsl_get_sampler_result_type(type)); +} - switch (tex->op) { - case nir_texop_tex: - case nir_texop_txb: - case nir_texop_txd: - case nir_texop_txl: - case nir_texop_txs: - case nir_texop_lod: - case nir_texop_tg4: - break; - default: - return false; +static bool +lower_int_cubmap_to_array_filter(const nir_instr *instr, + UNUSED const void *_options) +{ + if (instr->type == nir_instr_type_intrinsic) { + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + switch (intr->intrinsic) { + case nir_intrinsic_image_atomic_add: + case nir_intrinsic_image_atomic_and: + case nir_intrinsic_image_atomic_comp_swap: + case nir_intrinsic_image_atomic_dec_wrap: + case nir_intrinsic_image_atomic_exchange: + case nir_intrinsic_image_atomic_fadd: + case nir_intrinsic_image_atomic_fmax: + case nir_intrinsic_image_atomic_fmin: + case nir_intrinsic_image_atomic_imax: + case nir_intrinsic_image_atomic_imin: + case nir_intrinsic_image_atomic_inc_wrap: + case nir_intrinsic_image_atomic_or: + case nir_intrinsic_image_atomic_umax: + case nir_intrinsic_image_atomic_umin: + case nir_intrinsic_image_atomic_xor: + case nir_intrinsic_image_load: + case nir_intrinsic_image_size: + case nir_intrinsic_image_store: + case nir_intrinsic_image_deref_atomic_add: + case nir_intrinsic_image_deref_atomic_and: + case nir_intrinsic_image_deref_atomic_comp_swap: + case nir_intrinsic_image_deref_atomic_dec_wrap: + case nir_intrinsic_image_deref_atomic_exchange: + case nir_intrinsic_image_deref_atomic_fadd: + case nir_intrinsic_image_deref_atomic_fmax: + case nir_intrinsic_image_deref_atomic_fmin: + case nir_intrinsic_image_deref_atomic_imax: + case nir_intrinsic_image_deref_atomic_imin: + case nir_intrinsic_image_deref_atomic_inc_wrap: + case nir_intrinsic_image_deref_atomic_or: + case nir_intrinsic_image_deref_atomic_umax: + case nir_intrinsic_image_deref_atomic_umin: + case nir_intrinsic_image_deref_atomic_xor: + case nir_intrinsic_image_deref_load: + case nir_intrinsic_image_deref_size: + case nir_intrinsic_image_deref_store: + return nir_intrinsic_image_dim(intr) == GLSL_SAMPLER_DIM_CUBE; + default: + return false; + } + } else if (instr->type == nir_instr_type_deref) { + nir_deref_instr *deref = nir_instr_as_deref(instr); + return type_needs_lowering(deref->type); + } else if (instr->type == nir_instr_type_tex) { + nir_tex_instr *tex = nir_instr_as_tex(instr); + + if (tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE) + return false; + + switch (tex->op) { + case nir_texop_tex: + case nir_texop_txb: + case nir_texop_txd: + case nir_texop_txl: + case nir_texop_txs: + case nir_texop_lod: + case nir_texop_tg4: + break; + default: + return false; + } + + int sampler_deref = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref); + assert(sampler_deref >= 0); + nir_deref_instr *deref = nir_instr_as_deref(tex->src[sampler_deref].src.ssa->parent_instr); + nir_variable *cube = nir_deref_instr_get_variable(deref); + return glsl_base_type_is_integer(glsl_get_sampler_result_type(cube->type)); } - int sampler_deref = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref); - assert(sampler_deref >= 0); - nir_deref_instr *deref = nir_instr_as_deref(tex->src[sampler_deref].src.ssa->parent_instr); - nir_variable *cube = nir_deref_instr_get_variable(deref); - return glsl_base_type_is_integer(glsl_get_sampler_result_type(cube->type)); + return false; } typedef struct { + bool image; nir_ssa_def *rx; nir_ssa_def *ry; nir_ssa_def *rz; @@ -84,7 +145,9 @@ evaluate_face_x(nir_builder *b, coord_t *coord) if (coord->array) face = nir_fadd(b, face, coord->array); - return nir_vec3(b, x,y, face); + return coord->image ? + nir_vec4(b, x,y, face, nir_ssa_undef(b, 1, 32)) : + nir_vec3(b, x,y, face); } static nir_ssa_def * @@ -100,8 +163,10 @@ evaluate_face_y(nir_builder *b, coord_t *coord) if (coord->array) face = nir_fadd(b, face, coord->array); - - return nir_vec3(b, x,y, face); + + return coord->image ? + nir_vec4(b, x,y, face, nir_ssa_undef(b, 1, 32)) : + nir_vec3(b, x,y, face); } static nir_ssa_def * @@ -117,8 +182,10 @@ evaluate_face_z(nir_builder *b, coord_t *coord) if (coord->array) face = nir_fadd(b, face, coord->array); - - return nir_vec3(b, x,y, face); + + return coord->image ? + nir_vec4(b, x,y, face, nir_ssa_undef(b, 1, 32)) : + nir_vec3(b, x,y, face); } static nir_ssa_def * @@ -311,15 +378,10 @@ handle_cube_gather(nir_builder *b, nir_tex_instr *tex, nir_ssa_def *coord) } static nir_ssa_def * -lower_cube_sample(nir_builder *b, nir_tex_instr *tex) +lower_cube_coords(nir_builder *b, nir_ssa_def *coord, bool is_array, bool is_image) { - int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord); - assert(coord_index >= 0); - - /* Evaluate the face and the xy coordinates for a 2D tex op */ - nir_ssa_def *coord = tex->src[coord_index].src.ssa; - coord_t coords; + coords.image = is_image; coords.rx = nir_channel(b, coord, 0); coords.ry = nir_channel(b, coord, 1); coords.rz = nir_channel(b, coord, 2); @@ -327,7 +389,7 @@ lower_cube_sample(nir_builder *b, nir_tex_instr *tex) coords.ary = nir_fabs(b, coords.ry); coords.arz = nir_fabs(b, coords.rz); coords.array = NULL; - if (tex->is_array) + if (is_array) coords.array = nir_fmul(b, nir_channel(b, coord, 3), nir_imm_float(b, 6.0f)); nir_ssa_def *use_face_x = nir_iand(b, @@ -355,6 +417,19 @@ lower_cube_sample(nir_builder *b, nir_tex_instr *tex) // This contains in xy the normalized sample coordinates, and in z the face index nir_ssa_def *coord_and_face = nir_if_phi(b, face_x_coord, face_y_or_z_coord); + return coord_and_face; +} + +static nir_ssa_def * +lower_cube_sample(nir_builder *b, nir_tex_instr *tex) +{ + int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord); + assert(coord_index >= 0); + + /* Evaluate the face and the xy coordinates for a 2D tex op */ + nir_ssa_def *coord = tex->src[coord_index].src.ssa; + nir_ssa_def *coord_and_face = lower_cube_coords(b, coord, tex->is_array, false); + if (tex->op == nir_texop_tg4) return handle_cube_gather(b, tex, coord_and_face); else @@ -362,6 +437,16 @@ lower_cube_sample(nir_builder *b, nir_tex_instr *tex) } static nir_ssa_def * +lower_cube_image_load_store_atomic(nir_builder *b, nir_intrinsic_instr *intr) +{ + b->cursor = nir_before_instr(&intr->instr); + nir_intrinsic_set_image_array(intr, true); + nir_intrinsic_set_image_dim(intr, GLSL_SAMPLER_DIM_2D); + + return NIR_LOWER_INSTR_PROGRESS; +} + +static nir_ssa_def * lower_cube_txs(nir_builder *b, nir_tex_instr *tex) { b->cursor = nir_after_instr(&tex->instr); @@ -375,8 +460,22 @@ lower_cube_txs(nir_builder *b, nir_tex_instr *tex) cube_array_dim); } +static nir_ssa_def * +lower_cube_image_size(nir_builder *b, nir_intrinsic_instr *intr) +{ + b->cursor = nir_after_instr(&intr->instr); + if (!nir_intrinsic_image_array(intr)) + return nir_channels(b, &intr->dest.ssa, 3); + + nir_ssa_def *array_dim = nir_channel(b, &intr->dest.ssa, 2); + nir_ssa_def *cube_array_dim = nir_idiv(b, array_dim, nir_imm_int(b, 6)); + return nir_vec3(b, nir_channel(b, &intr->dest.ssa, 0), + nir_channel(b, &intr->dest.ssa, 1), + cube_array_dim); +} + static const struct glsl_type * -make_2darray_from_cubemap(const struct glsl_type *type) +make_2darray_sampler_from_cubemap(const struct glsl_type *type) { return glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE ? glsl_sampler_type( @@ -386,31 +485,31 @@ make_2darray_from_cubemap(const struct glsl_type *type) } static const struct glsl_type * -make_2darray_from_cubemap_with_array(const struct glsl_type *type) +make_2darray_image_from_cubemap(const struct glsl_type *type) +{ + return glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE ? + glsl_image_type( + GLSL_SAMPLER_DIM_2D, + true, + glsl_get_sampler_result_type(type)) : type; +} + +static const struct glsl_type * +make_2darray_from_cubemap_with_array(const struct glsl_type *type, bool is_image) { if (glsl_type_is_array(type)) { const struct glsl_type *new_type = glsl_without_array(type); - return new_type != type ? glsl_array_type(make_2darray_from_cubemap(glsl_without_array(type)), + return new_type != type ? glsl_array_type(make_2darray_from_cubemap_with_array(glsl_without_array(type), is_image), glsl_get_length(type), 0) : type; - } else - return make_2darray_from_cubemap(type); + } else if (is_image) + return make_2darray_image_from_cubemap(type); + else + return make_2darray_sampler_from_cubemap(type); } static nir_ssa_def * -lower_int_cubmap_to_array_impl(nir_builder *b, nir_instr *instr, - UNUSED void *_options) +lower_int_cubemap_to_array_tex(nir_builder *b, nir_tex_instr *tex) { - nir_tex_instr *tex = nir_instr_as_tex(instr); - - int sampler_index = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref); - assert(sampler_index >= 0); - - nir_deref_instr *sampler_deref = nir_instr_as_deref(tex->src[sampler_index].src.ssa->parent_instr); - nir_variable *sampler = nir_deref_instr_get_variable(sampler_deref); - - sampler->type = make_2darray_from_cubemap_with_array(sampler->type); - sampler_deref->type = sampler->type; - switch (tex->op) { case nir_texop_tex: case nir_texop_txb: @@ -426,6 +525,38 @@ lower_int_cubmap_to_array_impl(nir_builder *b, nir_instr *instr, } } +static nir_ssa_def * +lower_cube_intrinsic(nir_builder *b, nir_intrinsic_instr *intr) +{ + if (intr->intrinsic == nir_intrinsic_image_size || + intr->intrinsic == nir_intrinsic_image_deref_size) + return lower_cube_image_size(b, intr); + else + return lower_cube_image_load_store_atomic(b, intr); +} + +static nir_ssa_def * +lower_cube_deref(nir_builder *b, nir_deref_instr *deref) +{ + deref->type = make_2darray_from_cubemap_with_array( + deref->type, + glsl_type_is_image(glsl_without_array(deref->type))); + return NIR_LOWER_INSTR_PROGRESS; +} + +static nir_ssa_def * +lower_int_cubmap_to_array_impl(nir_builder *b, nir_instr *instr, + UNUSED void *_options) +{ + if (instr->type == nir_instr_type_tex) + return lower_int_cubemap_to_array_tex(b, nir_instr_as_tex(instr)); + else if (instr->type == nir_instr_type_intrinsic) + return lower_cube_intrinsic(b, nir_instr_as_intrinsic(instr)); + else if (instr->type == nir_instr_type_deref) + return lower_cube_deref(b, nir_instr_as_deref(instr)); + return NULL; +} + bool d3d12_lower_int_cubmap_to_array(nir_shader *s) { @@ -436,13 +567,11 @@ d3d12_lower_int_cubmap_to_array(nir_shader *s) NULL); if (result) { - nir_foreach_variable_with_modes_safe(var, s, nir_var_uniform) { - if (glsl_type_is_sampler(var->type)) { - if (glsl_get_sampler_dim(var->type) == GLSL_SAMPLER_DIM_CUBE && - (glsl_base_type_is_integer(glsl_get_sampler_result_type(var->type)))) { - var->type = make_2darray_from_cubemap_with_array(var->type); - } - } + nir_foreach_variable_with_modes_safe(var, s, nir_var_uniform | nir_var_image) { + if (!type_needs_lowering(var->type)) + continue; + bool is_image = glsl_type_is_image(glsl_without_array(var->type)); + var->type = make_2darray_from_cubemap_with_array(var->type, is_image); } } return result; -- 2.7.4