mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-01 10:18:05 +02:00
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 <sivileri@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14342>
This commit is contained in:
parent
d0a3794d6d
commit
63fe4888ea
1 changed files with 188 additions and 59 deletions
|
|
@ -26,39 +26,100 @@
|
|||
#include "nir_builder.h"
|
||||
#include "nir_builtin_builder.h"
|
||||
|
||||
static bool
|
||||
type_needs_lowering(const struct glsl_type *type)
|
||||
{
|
||||
type = glsl_without_array(type);
|
||||
if (!glsl_type_is_image(type) && !glsl_type_is_sampler(type))
|
||||
return false;
|
||||
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));
|
||||
}
|
||||
|
||||
static bool
|
||||
lower_int_cubmap_to_array_filter(const nir_instr *instr,
|
||||
UNUSED const void *_options)
|
||||
{
|
||||
if (instr->type != nir_instr_type_tex)
|
||||
return false;
|
||||
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);
|
||||
|
||||
nir_tex_instr *tex = nir_instr_as_tex(instr);
|
||||
if (tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE)
|
||||
return false;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,12 +417,35 @@ 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
|
||||
return create_array_tex_from_cube_tex(b, tex, coord_and_face, tex->op);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue