#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;
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 *
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 *
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 *
}
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);
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,
// 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
}
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);
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(
}
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:
}
}
+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)
{
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;