2019-05-26 09:43:12 +01:00
|
|
|
/*
|
|
|
|
* Copyright © Microsoft Corporation
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
|
|
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
|
|
|
* the Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
|
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
|
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2022-06-08 14:53:44 +01:00
|
|
|
#include "dxil_nir_lower_int_cubemaps.h"
|
2019-05-26 09:43:12 +01:00
|
|
|
|
|
|
|
#include "nir_builder.h"
|
|
|
|
#include "nir_builtin_builder.h"
|
|
|
|
|
|
|
|
static bool
|
2021-12-29 17:59:33 +00:00
|
|
|
type_needs_lowering(const struct glsl_type *type)
|
2019-05-26 09:43:12 +01:00
|
|
|
{
|
2021-12-29 17:59:33 +00:00
|
|
|
type = glsl_without_array(type);
|
|
|
|
if (!glsl_type_is_image(type) && !glsl_type_is_sampler(type))
|
2019-05-26 09:43:12 +01:00
|
|
|
return false;
|
2021-12-29 17:59:33 +00:00
|
|
|
if (glsl_get_sampler_dim(type) != GLSL_SAMPLER_DIM_CUBE)
|
2019-05-26 09:43:12 +01:00
|
|
|
return false;
|
2021-12-29 17:59:33 +00:00
|
|
|
if (glsl_type_is_image(type))
|
|
|
|
return true;
|
|
|
|
return glsl_base_type_is_integer(glsl_get_sampler_result_type(type));
|
|
|
|
}
|
2019-05-26 09:43:12 +01:00
|
|
|
|
2021-12-29 17:59:33 +00:00
|
|
|
static bool
|
|
|
|
lower_int_cubmap_to_array_filter(const nir_instr *instr,
|
2022-06-08 15:03:37 +01:00
|
|
|
const void *options)
|
2021-12-29 17:59:33 +00:00
|
|
|
{
|
2022-06-08 15:03:37 +01:00
|
|
|
bool lower_samplers = *(bool *)options;
|
2021-12-29 17:59:33 +00:00
|
|
|
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);
|
2022-06-08 15:03:37 +01:00
|
|
|
} else if (instr->type == nir_instr_type_tex && lower_samplers) {
|
2021-12-29 17:59:33 +00:00
|
|
|
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));
|
2019-05-26 09:43:12 +01:00
|
|
|
}
|
|
|
|
|
2021-12-29 17:59:33 +00:00
|
|
|
return false;
|
2019-05-26 09:43:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
2021-12-29 17:59:33 +00:00
|
|
|
bool image;
|
2019-05-26 09:43:12 +01:00
|
|
|
nir_ssa_def *rx;
|
|
|
|
nir_ssa_def *ry;
|
|
|
|
nir_ssa_def *rz;
|
|
|
|
nir_ssa_def *arx;
|
|
|
|
nir_ssa_def *ary;
|
|
|
|
nir_ssa_def *arz;
|
2021-12-08 15:05:53 +00:00
|
|
|
nir_ssa_def *array;
|
2019-05-26 09:43:12 +01:00
|
|
|
} coord_t;
|
|
|
|
|
|
|
|
|
|
|
|
/* This is taken from from sp_tex_sample:convert_cube */
|
|
|
|
static nir_ssa_def *
|
|
|
|
evaluate_face_x(nir_builder *b, coord_t *coord)
|
|
|
|
{
|
|
|
|
nir_ssa_def *sign = nir_fsign(b, coord->rx);
|
|
|
|
nir_ssa_def *positive = nir_fge(b, coord->rx, nir_imm_float(b, 0.0));
|
|
|
|
nir_ssa_def *ima = nir_fdiv(b, nir_imm_float(b, -0.5), coord->arx);
|
|
|
|
|
|
|
|
nir_ssa_def *x = nir_fadd(b, nir_fmul(b, nir_fmul(b, sign, ima), coord->rz), nir_imm_float(b, 0.5));
|
|
|
|
nir_ssa_def *y = nir_fadd(b, nir_fmul(b, ima, coord->ry), nir_imm_float(b, 0.5));
|
|
|
|
nir_ssa_def *face = nir_bcsel(b, positive, nir_imm_float(b, 0.0), nir_imm_float(b, 1.0));
|
|
|
|
|
2021-12-08 15:05:53 +00:00
|
|
|
if (coord->array)
|
|
|
|
face = nir_fadd(b, face, coord->array);
|
|
|
|
|
2021-12-29 17:59:33 +00:00
|
|
|
return coord->image ?
|
|
|
|
nir_vec4(b, x,y, face, nir_ssa_undef(b, 1, 32)) :
|
|
|
|
nir_vec3(b, x,y, face);
|
2019-05-26 09:43:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static nir_ssa_def *
|
|
|
|
evaluate_face_y(nir_builder *b, coord_t *coord)
|
|
|
|
{
|
|
|
|
nir_ssa_def *sign = nir_fsign(b, coord->ry);
|
|
|
|
nir_ssa_def *positive = nir_fge(b, coord->ry, nir_imm_float(b, 0.0));
|
|
|
|
nir_ssa_def *ima = nir_fdiv(b, nir_imm_float(b, 0.5), coord->ary);
|
|
|
|
|
|
|
|
nir_ssa_def *x = nir_fadd(b, nir_fmul(b, ima, coord->rx), nir_imm_float(b, 0.5));
|
|
|
|
nir_ssa_def *y = nir_fadd(b, nir_fmul(b, nir_fmul(b, sign, ima), coord->rz), nir_imm_float(b, 0.5));
|
|
|
|
nir_ssa_def *face = nir_bcsel(b, positive, nir_imm_float(b, 2.0), nir_imm_float(b, 3.0));
|
|
|
|
|
2021-12-08 15:05:53 +00:00
|
|
|
if (coord->array)
|
|
|
|
face = nir_fadd(b, face, coord->array);
|
2021-12-29 17:59:33 +00:00
|
|
|
|
|
|
|
return coord->image ?
|
|
|
|
nir_vec4(b, x,y, face, nir_ssa_undef(b, 1, 32)) :
|
|
|
|
nir_vec3(b, x,y, face);
|
2019-05-26 09:43:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static nir_ssa_def *
|
|
|
|
evaluate_face_z(nir_builder *b, coord_t *coord)
|
|
|
|
{
|
|
|
|
nir_ssa_def *sign = nir_fsign(b, coord->rz);
|
|
|
|
nir_ssa_def *positive = nir_fge(b, coord->rz, nir_imm_float(b, 0.0));
|
|
|
|
nir_ssa_def *ima = nir_fdiv(b, nir_imm_float(b, -0.5), coord->arz);
|
|
|
|
|
|
|
|
nir_ssa_def *x = nir_fadd(b, nir_fmul(b, nir_fmul(b, sign, ima), nir_fneg(b, coord->rx)), nir_imm_float(b, 0.5));
|
|
|
|
nir_ssa_def *y = nir_fadd(b, nir_fmul(b, ima, coord->ry), nir_imm_float(b, 0.5));
|
|
|
|
nir_ssa_def *face = nir_bcsel(b, positive, nir_imm_float(b, 4.0), nir_imm_float(b, 5.0));
|
|
|
|
|
2021-12-08 15:05:53 +00:00
|
|
|
if (coord->array)
|
|
|
|
face = nir_fadd(b, face, coord->array);
|
2021-12-29 17:59:33 +00:00
|
|
|
|
|
|
|
return coord->image ?
|
|
|
|
nir_vec4(b, x,y, face, nir_ssa_undef(b, 1, 32)) :
|
|
|
|
nir_vec3(b, x,y, face);
|
2019-05-26 09:43:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static nir_ssa_def *
|
2021-12-09 21:38:58 +00:00
|
|
|
create_array_tex_from_cube_tex(nir_builder *b, nir_tex_instr *tex, nir_ssa_def *coord, nir_texop op)
|
2019-05-26 09:43:12 +01:00
|
|
|
{
|
|
|
|
nir_tex_instr *array_tex;
|
|
|
|
|
|
|
|
array_tex = nir_tex_instr_create(b->shader, tex->num_srcs);
|
2021-12-09 21:38:58 +00:00
|
|
|
array_tex->op = op;
|
2019-05-26 09:43:12 +01:00
|
|
|
array_tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
|
|
|
|
array_tex->is_array = true;
|
|
|
|
array_tex->is_shadow = tex->is_shadow;
|
|
|
|
array_tex->is_new_style_shadow = tex->is_new_style_shadow;
|
|
|
|
array_tex->texture_index = tex->texture_index;
|
|
|
|
array_tex->sampler_index = tex->sampler_index;
|
|
|
|
array_tex->dest_type = tex->dest_type;
|
|
|
|
array_tex->coord_components = 3;
|
|
|
|
|
|
|
|
nir_src coord_src = nir_src_for_ssa(coord);
|
|
|
|
for (unsigned i = 0; i < tex->num_srcs; i++) {
|
|
|
|
nir_src *psrc = (tex->src[i].src_type == nir_tex_src_coord) ?
|
|
|
|
&coord_src : &tex->src[i].src;
|
|
|
|
|
2021-07-07 19:06:11 +01:00
|
|
|
nir_src_copy(&array_tex->src[i].src, psrc);
|
2019-05-26 09:43:12 +01:00
|
|
|
array_tex->src[i].src_type = tex->src[i].src_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
nir_ssa_dest_init(&array_tex->instr, &array_tex->dest,
|
|
|
|
nir_tex_instr_dest_size(array_tex), 32, NULL);
|
|
|
|
nir_builder_instr_insert(b, &array_tex->instr);
|
|
|
|
return &array_tex->dest.ssa;
|
|
|
|
}
|
|
|
|
|
2021-12-09 21:38:58 +00:00
|
|
|
static nir_ssa_def *
|
|
|
|
handle_cube_edge(nir_builder *b, nir_ssa_def *x, nir_ssa_def *y, nir_ssa_def *face, nir_ssa_def *array_slice_cube_base, nir_ssa_def *tex_size)
|
|
|
|
{
|
|
|
|
enum cube_remap
|
|
|
|
{
|
|
|
|
cube_remap_zero = 0,
|
|
|
|
cube_remap_x,
|
|
|
|
cube_remap_y,
|
|
|
|
cube_remap_tex_size,
|
|
|
|
cube_remap_tex_size_minus_x,
|
|
|
|
cube_remap_tex_size_minus_y,
|
|
|
|
|
|
|
|
cube_remap_size,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct cube_remap_table
|
|
|
|
{
|
|
|
|
enum cube_remap remap_x;
|
|
|
|
enum cube_remap remap_y;
|
|
|
|
uint32_t remap_face;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct cube_remap_table cube_remap_neg_x[6] =
|
|
|
|
{
|
|
|
|
{cube_remap_tex_size, cube_remap_y, 4},
|
|
|
|
{cube_remap_tex_size, cube_remap_y, 5},
|
|
|
|
{cube_remap_y, cube_remap_zero, 1},
|
|
|
|
{cube_remap_tex_size_minus_y, cube_remap_tex_size, 1},
|
|
|
|
{cube_remap_tex_size, cube_remap_y, 1},
|
|
|
|
{cube_remap_tex_size, cube_remap_y, 0},
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct cube_remap_table cube_remap_pos_x[6] =
|
|
|
|
{
|
|
|
|
{cube_remap_zero, cube_remap_y, 5},
|
|
|
|
{cube_remap_zero, cube_remap_y, 4},
|
|
|
|
{cube_remap_tex_size_minus_y, cube_remap_zero, 0},
|
|
|
|
{cube_remap_y, cube_remap_tex_size, 0},
|
|
|
|
{cube_remap_zero, cube_remap_y, 0},
|
|
|
|
{cube_remap_zero, cube_remap_y, 1},
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct cube_remap_table cube_remap_neg_y[6] =
|
|
|
|
{
|
|
|
|
{cube_remap_tex_size, cube_remap_tex_size_minus_x, 2},
|
|
|
|
{cube_remap_zero, cube_remap_x, 2},
|
|
|
|
{cube_remap_tex_size_minus_x, cube_remap_zero, 5},
|
|
|
|
{cube_remap_x, cube_remap_tex_size, 4},
|
|
|
|
{cube_remap_x, cube_remap_tex_size, 2},
|
|
|
|
{cube_remap_tex_size_minus_x, cube_remap_zero, 2},
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct cube_remap_table cube_remap_pos_y[6] =
|
|
|
|
{
|
|
|
|
{cube_remap_tex_size, cube_remap_x, 3},
|
|
|
|
{cube_remap_zero, cube_remap_tex_size_minus_x, 3},
|
|
|
|
{cube_remap_x, cube_remap_zero, 4},
|
|
|
|
{cube_remap_tex_size_minus_x, cube_remap_tex_size, 5},
|
|
|
|
{cube_remap_x, cube_remap_zero, 3},
|
|
|
|
{cube_remap_tex_size_minus_x, cube_remap_tex_size, 3},
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct cube_remap_table* remap_tables[4] = {
|
|
|
|
cube_remap_neg_x,
|
|
|
|
cube_remap_pos_x,
|
|
|
|
cube_remap_neg_y,
|
|
|
|
cube_remap_pos_y
|
|
|
|
};
|
|
|
|
|
|
|
|
nir_ssa_def *zero = nir_imm_int(b, 0);
|
|
|
|
|
|
|
|
/* Doesn't matter since the texture is square */
|
|
|
|
tex_size = nir_channel(b, tex_size, 0);
|
|
|
|
|
|
|
|
nir_ssa_def *x_on = nir_iand(b, nir_ige(b, x, zero), nir_ige(b, tex_size, x));
|
|
|
|
nir_ssa_def *y_on = nir_iand(b, nir_ige(b, y, zero), nir_ige(b, tex_size, y));
|
|
|
|
nir_ssa_def *one_on = nir_ixor(b, x_on, y_on);
|
|
|
|
|
|
|
|
/* If the sample did not fall off the face in either dimension, then set output = input */
|
|
|
|
nir_ssa_def *x_result = x;
|
|
|
|
nir_ssa_def *y_result = y;
|
|
|
|
nir_ssa_def *face_result = face;
|
|
|
|
|
|
|
|
/* otherwise, if the sample fell off the face in either the X or the Y direction, remap to the new face */
|
|
|
|
nir_ssa_def *remap_predicates[4] =
|
|
|
|
{
|
|
|
|
nir_iand(b, one_on, nir_ilt(b, x, zero)),
|
|
|
|
nir_iand(b, one_on, nir_ilt(b, tex_size, x)),
|
|
|
|
nir_iand(b, one_on, nir_ilt(b, y, zero)),
|
|
|
|
nir_iand(b, one_on, nir_ilt(b, tex_size, y)),
|
|
|
|
};
|
|
|
|
|
|
|
|
nir_ssa_def *remap_array[cube_remap_size];
|
|
|
|
|
|
|
|
remap_array[cube_remap_zero] = zero;
|
|
|
|
remap_array[cube_remap_x] = x;
|
|
|
|
remap_array[cube_remap_y] = y;
|
|
|
|
remap_array[cube_remap_tex_size] = tex_size;
|
|
|
|
remap_array[cube_remap_tex_size_minus_x] = nir_isub(b, tex_size, x);
|
|
|
|
remap_array[cube_remap_tex_size_minus_y] = nir_isub(b, tex_size, y);
|
|
|
|
|
|
|
|
/* For each possible way the sample could have fallen off */
|
|
|
|
for (unsigned i = 0; i < 4; i++) {
|
|
|
|
const struct cube_remap_table* remap_table = remap_tables[i];
|
|
|
|
|
|
|
|
/* For each possible original face */
|
|
|
|
for (unsigned j = 0; j < 6; j++) {
|
|
|
|
nir_ssa_def *predicate = nir_iand(b, remap_predicates[i], nir_ieq(b, face, nir_imm_int(b, j)));
|
|
|
|
|
|
|
|
x_result = nir_bcsel(b, predicate, remap_array[remap_table[j].remap_x], x_result);
|
|
|
|
y_result = nir_bcsel(b, predicate, remap_array[remap_table[j].remap_y], y_result);
|
|
|
|
face_result = nir_bcsel(b, predicate, remap_array[remap_table[j].remap_face], face_result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nir_vec3(b, x_result, y_result, nir_iadd(b, face_result, array_slice_cube_base));
|
|
|
|
}
|
|
|
|
|
|
|
|
static nir_ssa_def *
|
|
|
|
handle_cube_gather(nir_builder *b, nir_tex_instr *tex, nir_ssa_def *coord)
|
|
|
|
{
|
|
|
|
nir_ssa_def *tex_size = nir_get_texture_size(b, tex);
|
|
|
|
|
|
|
|
/* nir_get_texture_size puts the cursor before the tex op */
|
|
|
|
b->cursor = nir_after_instr(coord->parent_instr);
|
|
|
|
|
|
|
|
nir_ssa_def *const_05 = nir_imm_float(b, 0.5f);
|
|
|
|
nir_ssa_def *texel_coords = nir_fmul(b, nir_channels(b, coord, 3),
|
|
|
|
nir_i2f32(b, nir_channels(b, tex_size, 3)));
|
|
|
|
|
|
|
|
nir_ssa_def *x_orig = nir_channel(b, texel_coords, 0);
|
|
|
|
nir_ssa_def *y_orig = nir_channel(b, texel_coords, 1);
|
|
|
|
|
|
|
|
nir_ssa_def *x_pos = nir_f2i32(b, nir_fadd(b, x_orig, const_05));
|
|
|
|
nir_ssa_def *x_neg = nir_f2i32(b, nir_fsub(b, x_orig, const_05));
|
|
|
|
nir_ssa_def *y_pos = nir_f2i32(b, nir_fadd(b, y_orig, const_05));
|
|
|
|
nir_ssa_def *y_neg = nir_f2i32(b, nir_fsub(b, y_orig, const_05));
|
|
|
|
nir_ssa_def *coords[4][2] = {
|
|
|
|
{ x_neg, y_pos },
|
|
|
|
{ x_pos, y_pos },
|
|
|
|
{ x_pos, y_neg },
|
|
|
|
{ x_neg, y_neg },
|
|
|
|
};
|
|
|
|
|
|
|
|
nir_ssa_def *array_slice_2d = nir_f2i32(b, nir_channel(b, coord, 2));
|
|
|
|
nir_ssa_def *face = nir_imod(b, array_slice_2d, nir_imm_int(b, 6));
|
|
|
|
nir_ssa_def *array_slice_cube_base = nir_isub(b, array_slice_2d, face);
|
|
|
|
|
|
|
|
nir_ssa_def *channels[4];
|
|
|
|
for (unsigned i = 0; i < 4; ++i) {
|
|
|
|
nir_ssa_def *final_coord = handle_cube_edge(b, coords[i][0], coords[i][1], face, array_slice_cube_base, tex_size);
|
|
|
|
nir_ssa_def *sampled_val = create_array_tex_from_cube_tex(b, tex, final_coord, nir_texop_txf);
|
|
|
|
channels[i] = nir_channel(b, sampled_val, tex->component);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nir_vec(b, channels, 4);
|
|
|
|
}
|
|
|
|
|
2019-05-26 09:43:12 +01:00
|
|
|
static nir_ssa_def *
|
2021-12-29 17:59:33 +00:00
|
|
|
lower_cube_coords(nir_builder *b, nir_ssa_def *coord, bool is_array, bool is_image)
|
2019-05-26 09:43:12 +01:00
|
|
|
{
|
|
|
|
coord_t coords;
|
2021-12-29 17:59:33 +00:00
|
|
|
coords.image = is_image;
|
2019-05-26 09:43:12 +01:00
|
|
|
coords.rx = nir_channel(b, coord, 0);
|
|
|
|
coords.ry = nir_channel(b, coord, 1);
|
|
|
|
coords.rz = nir_channel(b, coord, 2);
|
|
|
|
coords.arx = nir_fabs(b, coords.rx);
|
|
|
|
coords.ary = nir_fabs(b, coords.ry);
|
|
|
|
coords.arz = nir_fabs(b, coords.rz);
|
2021-12-08 15:05:53 +00:00
|
|
|
coords.array = NULL;
|
2021-12-29 17:59:33 +00:00
|
|
|
if (is_array)
|
2021-12-08 15:05:53 +00:00
|
|
|
coords.array = nir_fmul(b, nir_channel(b, coord, 3), nir_imm_float(b, 6.0f));
|
2019-05-26 09:43:12 +01:00
|
|
|
|
|
|
|
nir_ssa_def *use_face_x = nir_iand(b,
|
|
|
|
nir_fge(b, coords.arx, coords.ary),
|
|
|
|
nir_fge(b, coords.arx, coords.arz));
|
|
|
|
|
|
|
|
nir_if *use_face_x_if = nir_push_if(b, use_face_x);
|
|
|
|
nir_ssa_def *face_x_coord = evaluate_face_x(b, &coords);
|
|
|
|
nir_if *use_face_x_else = nir_push_else(b, use_face_x_if);
|
|
|
|
|
|
|
|
nir_ssa_def *use_face_y = nir_iand(b,
|
|
|
|
nir_fge(b, coords.ary, coords.arx),
|
|
|
|
nir_fge(b, coords.ary, coords.arz));
|
|
|
|
|
|
|
|
nir_if *use_face_y_if = nir_push_if(b, use_face_y);
|
|
|
|
nir_ssa_def *face_y_coord = evaluate_face_y(b, &coords);
|
|
|
|
nir_if *use_face_y_else = nir_push_else(b, use_face_y_if);
|
|
|
|
|
|
|
|
nir_ssa_def *face_z_coord = evaluate_face_z(b, &coords);
|
|
|
|
|
|
|
|
nir_pop_if(b, use_face_y_else);
|
|
|
|
nir_ssa_def *face_y_or_z_coord = nir_if_phi(b, face_y_coord, face_z_coord);
|
|
|
|
nir_pop_if(b, use_face_x_else);
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
2021-12-29 17:59:33 +00:00
|
|
|
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);
|
|
|
|
|
2021-12-09 21:38:58 +00:00
|
|
|
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);
|
2019-05-26 09:43:12 +01:00
|
|
|
}
|
|
|
|
|
2021-12-29 17:59:33 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-05-26 09:43:12 +01:00
|
|
|
static nir_ssa_def *
|
|
|
|
lower_cube_txs(nir_builder *b, nir_tex_instr *tex)
|
|
|
|
{
|
|
|
|
b->cursor = nir_after_instr(&tex->instr);
|
2021-12-08 15:05:53 +00:00
|
|
|
if (!tex->is_array)
|
|
|
|
return nir_channels(b, &tex->dest.ssa, 3);
|
|
|
|
|
|
|
|
nir_ssa_def *array_dim = nir_channel(b, &tex->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, &tex->dest.ssa, 0),
|
|
|
|
nir_channel(b, &tex->dest.ssa, 1),
|
|
|
|
cube_array_dim);
|
2019-05-26 09:43:12 +01:00
|
|
|
}
|
|
|
|
|
2021-12-29 17:59:33 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-05-26 09:43:12 +01:00
|
|
|
static const struct glsl_type *
|
2021-12-29 17:59:33 +00:00
|
|
|
make_2darray_sampler_from_cubemap(const struct glsl_type *type)
|
2019-05-26 09:43:12 +01:00
|
|
|
{
|
|
|
|
return glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE ?
|
|
|
|
glsl_sampler_type(
|
|
|
|
GLSL_SAMPLER_DIM_2D,
|
|
|
|
false, true,
|
|
|
|
glsl_get_sampler_result_type(type)) : type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct glsl_type *
|
2021-12-29 17:59:33 +00:00
|
|
|
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)
|
2019-05-26 09:43:12 +01:00
|
|
|
{
|
|
|
|
if (glsl_type_is_array(type)) {
|
|
|
|
const struct glsl_type *new_type = glsl_without_array(type);
|
2021-12-29 17:59:33 +00:00
|
|
|
return new_type != type ? glsl_array_type(make_2darray_from_cubemap_with_array(glsl_without_array(type), is_image),
|
2019-05-26 09:43:12 +01:00
|
|
|
glsl_get_length(type), 0) : type;
|
2021-12-29 17:59:33 +00:00
|
|
|
} else if (is_image)
|
|
|
|
return make_2darray_image_from_cubemap(type);
|
|
|
|
else
|
|
|
|
return make_2darray_sampler_from_cubemap(type);
|
2019-05-26 09:43:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static nir_ssa_def *
|
2021-12-29 17:59:33 +00:00
|
|
|
lower_int_cubemap_to_array_tex(nir_builder *b, nir_tex_instr *tex)
|
2019-05-26 09:43:12 +01:00
|
|
|
{
|
|
|
|
switch (tex->op) {
|
|
|
|
case nir_texop_tex:
|
|
|
|
case nir_texop_txb:
|
|
|
|
case nir_texop_txd:
|
|
|
|
case nir_texop_txl:
|
|
|
|
case nir_texop_lod:
|
2021-12-09 21:38:58 +00:00
|
|
|
case nir_texop_tg4:
|
2019-05-26 09:43:12 +01:00
|
|
|
return lower_cube_sample(b, tex);
|
|
|
|
case nir_texop_txs:
|
|
|
|
return lower_cube_txs(b, tex);
|
|
|
|
default:
|
|
|
|
unreachable("Unsupported cupe map texture operation");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-29 17:59:33 +00:00
|
|
|
static nir_ssa_def *
|
2022-06-08 14:45:57 +01:00
|
|
|
lower_cube_image_intrinsic(nir_builder *b, nir_intrinsic_instr *intr)
|
2021-12-29 17:59:33 +00:00
|
|
|
{
|
|
|
|
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 *
|
2022-06-08 14:45:57 +01:00
|
|
|
lower_cube_image_deref(nir_builder *b, nir_deref_instr *deref)
|
2021-12-29 17:59:33 +00:00
|
|
|
{
|
|
|
|
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,
|
2022-06-08 15:03:37 +01:00
|
|
|
void *options)
|
2021-12-29 17:59:33 +00:00
|
|
|
{
|
2022-06-08 15:03:37 +01:00
|
|
|
bool lower_samplers = *(bool *)options;
|
|
|
|
if (instr->type == nir_instr_type_tex && lower_samplers)
|
2021-12-29 17:59:33 +00:00
|
|
|
return lower_int_cubemap_to_array_tex(b, nir_instr_as_tex(instr));
|
|
|
|
else if (instr->type == nir_instr_type_intrinsic)
|
2022-06-08 14:45:57 +01:00
|
|
|
return lower_cube_image_intrinsic(b, nir_instr_as_intrinsic(instr));
|
2021-12-29 17:59:33 +00:00
|
|
|
else if (instr->type == nir_instr_type_deref)
|
2022-06-08 14:45:57 +01:00
|
|
|
return lower_cube_image_deref(b, nir_instr_as_deref(instr));
|
2021-12-29 17:59:33 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-05-26 09:43:12 +01:00
|
|
|
bool
|
2022-06-08 15:03:37 +01:00
|
|
|
dxil_nir_lower_int_cubemaps(nir_shader *s, bool lower_samplers)
|
2019-05-26 09:43:12 +01:00
|
|
|
{
|
|
|
|
bool result =
|
|
|
|
nir_shader_lower_instructions(s,
|
|
|
|
lower_int_cubmap_to_array_filter,
|
|
|
|
lower_int_cubmap_to_array_impl,
|
2022-06-08 15:03:37 +01:00
|
|
|
&lower_samplers);
|
2019-05-26 09:43:12 +01:00
|
|
|
|
|
|
|
if (result) {
|
2021-12-29 17:59:33 +00:00
|
|
|
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);
|
2019-05-26 09:43:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|