#include "compiler/nir/nir_builder.h"
#include "compiler/nir/nir_format_convert.h"
-/* The higher compiler layers use the GL enums for image formats even if
- * they come in from SPIR-V or Vulkan. We need to turn them into an ISL
- * enum before we can use them.
- */
-static enum isl_format
-isl_format_for_gl_format(uint32_t gl_format)
-{
- switch (gl_format) {
- case GL_R8: return ISL_FORMAT_R8_UNORM;
- case GL_R8_SNORM: return ISL_FORMAT_R8_SNORM;
- case GL_R8UI: return ISL_FORMAT_R8_UINT;
- case GL_R8I: return ISL_FORMAT_R8_SINT;
- case GL_RG8: return ISL_FORMAT_R8G8_UNORM;
- case GL_RG8_SNORM: return ISL_FORMAT_R8G8_SNORM;
- case GL_RG8UI: return ISL_FORMAT_R8G8_UINT;
- case GL_RG8I: return ISL_FORMAT_R8G8_SINT;
- case GL_RGBA8: return ISL_FORMAT_R8G8B8A8_UNORM;
- case GL_RGBA8_SNORM: return ISL_FORMAT_R8G8B8A8_SNORM;
- case GL_RGBA8UI: return ISL_FORMAT_R8G8B8A8_UINT;
- case GL_RGBA8I: return ISL_FORMAT_R8G8B8A8_SINT;
- case GL_R11F_G11F_B10F: return ISL_FORMAT_R11G11B10_FLOAT;
- case GL_RGB10_A2: return ISL_FORMAT_R10G10B10A2_UNORM;
- case GL_RGB10_A2UI: return ISL_FORMAT_R10G10B10A2_UINT;
- case GL_R16: return ISL_FORMAT_R16_UNORM;
- case GL_R16_SNORM: return ISL_FORMAT_R16_SNORM;
- case GL_R16F: return ISL_FORMAT_R16_FLOAT;
- case GL_R16UI: return ISL_FORMAT_R16_UINT;
- case GL_R16I: return ISL_FORMAT_R16_SINT;
- case GL_RG16: return ISL_FORMAT_R16G16_UNORM;
- case GL_RG16_SNORM: return ISL_FORMAT_R16G16_SNORM;
- case GL_RG16F: return ISL_FORMAT_R16G16_FLOAT;
- case GL_RG16UI: return ISL_FORMAT_R16G16_UINT;
- case GL_RG16I: return ISL_FORMAT_R16G16_SINT;
- case GL_RGBA16: return ISL_FORMAT_R16G16B16A16_UNORM;
- case GL_RGBA16_SNORM: return ISL_FORMAT_R16G16B16A16_SNORM;
- case GL_RGBA16F: return ISL_FORMAT_R16G16B16A16_FLOAT;
- case GL_RGBA16UI: return ISL_FORMAT_R16G16B16A16_UINT;
- case GL_RGBA16I: return ISL_FORMAT_R16G16B16A16_SINT;
- case GL_R32F: return ISL_FORMAT_R32_FLOAT;
- case GL_R32UI: return ISL_FORMAT_R32_UINT;
- case GL_R32I: return ISL_FORMAT_R32_SINT;
- case GL_RG32F: return ISL_FORMAT_R32G32_FLOAT;
- case GL_RG32UI: return ISL_FORMAT_R32G32_UINT;
- case GL_RG32I: return ISL_FORMAT_R32G32_SINT;
- case GL_RGBA32F: return ISL_FORMAT_R32G32B32A32_FLOAT;
- case GL_RGBA32UI: return ISL_FORMAT_R32G32B32A32_UINT;
- case GL_RGBA32I: return ISL_FORMAT_R32G32B32A32_SINT;
- case GL_NONE: return ISL_FORMAT_UNSUPPORTED;
- default:
- assert(!"Invalid image format");
- return ISL_FORMAT_UNSUPPORTED;
- }
-}
-
static nir_ssa_def *
_load_image_param(nir_builder *b, nir_deref_instr *deref, unsigned offset)
{
nir_intrinsic_set_base(load, offset / 4);
switch (offset) {
- case BRW_IMAGE_PARAM_SURFACE_IDX_OFFSET:
- load->num_components = 1;
- break;
case BRW_IMAGE_PARAM_OFFSET_OFFSET:
case BRW_IMAGE_PARAM_SWIZZLING_OFFSET:
load->num_components = 2;
#define load_image_param(b, d, o) \
_load_image_param(b, d, BRW_IMAGE_PARAM_##o##_OFFSET)
-static nir_ssa_def *
-sanitize_image_coord(nir_builder *b, nir_deref_instr *deref, nir_ssa_def *coord)
-{
- if (glsl_get_sampler_dim(deref->type) == GLSL_SAMPLER_DIM_1D &&
- glsl_sampler_type_is_array(deref->type)) {
- /* It's easier if 1D arrays are treated like 2D arrays */
- return nir_vec3(b, nir_channel(b, coord, 0),
- nir_imm_int(b, 0),
- nir_channel(b, coord, 1));
- } else {
- unsigned dims = glsl_get_sampler_coordinate_components(deref->type);
- return nir_channels(b, coord, (1 << dims) - 1);
- }
-}
-
static nir_ssa_def *
image_coord_is_in_bounds(nir_builder *b, nir_deref_instr *deref,
nir_ssa_def *coord)
{
- coord = sanitize_image_coord(b, deref, coord);
nir_ssa_def *size = load_image_param(b, deref, SIZE);
-
nir_ssa_def *cmp = nir_ilt(b, coord, size);
- nir_ssa_def *in_bounds = nir_imm_int(b, NIR_TRUE);
- for (unsigned i = 0; i < coord->num_components; i++)
+
+ unsigned coord_comps = glsl_get_sampler_coordinate_components(deref->type);
+ nir_ssa_def *in_bounds = nir_imm_true(b);
+ for (unsigned i = 0; i < coord_comps; i++)
in_bounds = nir_iand(b, in_bounds, nir_channel(b, cmp, i));
return in_bounds;
image_address(nir_builder *b, const struct gen_device_info *devinfo,
nir_deref_instr *deref, nir_ssa_def *coord)
{
- coord = sanitize_image_coord(b, deref, coord);
+ if (glsl_get_sampler_dim(deref->type) == GLSL_SAMPLER_DIM_1D &&
+ glsl_sampler_type_is_array(deref->type)) {
+ /* It's easier if 1D arrays are treated like 2D arrays */
+ coord = nir_vec3(b, nir_channel(b, coord, 0),
+ nir_imm_int(b, 0),
+ nir_channel(b, coord, 1));
+ } else {
+ unsigned dims = glsl_get_sampler_coordinate_components(deref->type);
+ coord = nir_channels(b, coord, (1 << dims) - 1);
+ }
nir_ssa_def *offset = load_image_param(b, deref, OFFSET);
nir_ssa_def *tiling = load_image_param(b, deref, TILING);
};
}
-static nir_ssa_def *
-nir_zero_vec(nir_builder *b, unsigned num_components)
-{
- nir_const_value v;
- memset(&v, 0, sizeof(v));
-
- return nir_build_imm(b, num_components, 32, v);
-}
-
static nir_ssa_def *
convert_color_for_load(nir_builder *b, const struct gen_device_info *devinfo,
nir_ssa_def *color,
nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
nir_variable *var = nir_deref_instr_get_variable(deref);
const enum isl_format image_fmt =
- isl_format_for_gl_format(var->data.image.format);
+ isl_format_for_pipe_format(var->data.image.format);
if (isl_has_matching_typed_storage_image_format(devinfo, image_fmt)) {
const enum isl_format lower_fmt =
nir_push_else(b, NULL);
- nir_ssa_def *zero = nir_zero_vec(b, load->num_components);
+ nir_ssa_def *zero = nir_imm_zero(b, load->num_components, 32);
nir_pop_if(b, NULL);
break;
case ISL_SFLOAT:
- if (image.bits[0] == 16) {
- nir_ssa_def *f16comps[4];
- for (unsigned i = 0; i < image.chans; i++) {
- f16comps[i] = nir_pack_half_2x16_split(b, nir_channel(b, color, i),
- nir_imm_float(b, 0));
- }
- color = nir_vec(b, f16comps, image.chans);
- }
+ if (image.bits[0] == 16)
+ color = nir_format_float_to_half(b, color);
break;
case ISL_UINT:
- if (image.bits[0] < 32) {
- nir_const_value max;
- for (unsigned i = 0; i < image.chans; i++) {
- assert(image.bits[i] < 32);
- max.u32[i] = (1u << image.bits[i]) - 1;
- }
- color = nir_umin(b, color, nir_build_imm(b, image.chans, 32, max));
- }
+ color = nir_format_clamp_uint(b, color, image.bits);
break;
case ISL_SINT:
- if (image.bits[0] < 32) {
- nir_const_value min, max;
- for (unsigned i = 0; i < image.chans; i++) {
- assert(image.bits[i] < 32);
- max.i32[i] = (1 << (image.bits[i] - 1)) - 1;
- min.i32[i] = -(1 << (image.bits[i] - 1));
- }
- color = nir_imin(b, color, nir_build_imm(b, image.chans, 32, max));
- color = nir_imax(b, color, nir_build_imm(b, image.chans, 32, min));
- }
+ color = nir_format_clamp_sint(b, color, image.bits);
break;
default:
/* For write-only surfaces, we trust that the hardware can just do the
* conversion for us.
*/
- if (var->data.image.write_only)
+ if (var->data.access & ACCESS_NON_READABLE)
return false;
const enum isl_format image_fmt =
- isl_format_for_gl_format(var->data.image.format);
+ isl_format_for_pipe_format(var->data.image.format);
if (isl_has_matching_typed_storage_image_format(devinfo, image_fmt)) {
const enum isl_format lower_fmt =
nir_intrinsic_instr *intrin)
{
nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
+ nir_variable *var = nir_deref_instr_get_variable(deref);
+
+ /* For write-only images, we have an actual image surface so we fall back
+ * and let the back-end emit a TXS for this.
+ */
+ if (var->data.access & ACCESS_NON_READABLE)
+ return false;
+
+ /* If we have a matching typed format, then we have an actual image surface
+ * so we fall back and let the back-end emit a TXS for this.
+ */
+ const enum isl_format image_fmt =
+ isl_format_for_pipe_format(var->data.image.format);
+ if (isl_has_matching_typed_storage_image_format(devinfo, image_fmt))
+ return false;
+
+ assert(nir_src_as_uint(intrin->src[1]) == 0);
b->cursor = nir_instr_remove(&intrin->instr);
enum glsl_sampler_dim dim = glsl_get_sampler_dim(deref->type);
unsigned coord_comps = glsl_get_sampler_coordinate_components(deref->type);
for (unsigned c = 0; c < coord_comps; c++) {
- if (c == 1 && dim == GLSL_SAMPLER_DIM_1D) {
- /* The array length for 1D arrays is in .z */
- comps[1] = nir_channel(b, size, 2);
- } else if (c == 2 && dim == GLSL_SAMPLER_DIM_CUBE) {
+ if (c == 2 && dim == GLSL_SAMPLER_DIM_CUBE) {
comps[2] = nir_idiv(b, nir_channel(b, size, 2), nir_imm_int(b, 6));
} else {
comps[c] = nir_channel(b, size, c);
bool
brw_nir_lower_image_load_store(nir_shader *shader,
- const struct gen_device_info *devinfo)
+ const struct gen_device_info *devinfo,
+ bool *uses_atomic_load_store)
{
bool progress = false;
if (function->impl == NULL)
continue;
+ bool impl_progress = false;
nir_foreach_block_safe(block, function->impl) {
nir_builder b;
nir_builder_init(&b, function->impl);
switch (intrin->intrinsic) {
case nir_intrinsic_image_deref_load:
if (lower_image_load_instr(&b, devinfo, intrin))
- progress = true;
+ impl_progress = true;
break;
case nir_intrinsic_image_deref_store:
if (lower_image_store_instr(&b, devinfo, intrin))
- progress = true;
+ impl_progress = true;
break;
case nir_intrinsic_image_deref_atomic_add:
- case nir_intrinsic_image_deref_atomic_min:
- case nir_intrinsic_image_deref_atomic_max:
+ case nir_intrinsic_image_deref_atomic_imin:
+ case nir_intrinsic_image_deref_atomic_umin:
+ case nir_intrinsic_image_deref_atomic_imax:
+ case nir_intrinsic_image_deref_atomic_umax:
case nir_intrinsic_image_deref_atomic_and:
case nir_intrinsic_image_deref_atomic_or:
case nir_intrinsic_image_deref_atomic_xor:
case nir_intrinsic_image_deref_atomic_exchange:
case nir_intrinsic_image_deref_atomic_comp_swap:
+ if (uses_atomic_load_store)
+ *uses_atomic_load_store = true;
if (lower_image_atomic_instr(&b, devinfo, intrin))
- progress = true;
+ impl_progress = true;
break;
case nir_intrinsic_image_deref_size:
if (lower_image_size_instr(&b, devinfo, intrin))
- progress = true;
+ impl_progress = true;
break;
default:
}
}
- nir_metadata_preserve(function->impl, nir_metadata_block_index |
- nir_metadata_dominance);
+ if (impl_progress) {
+ progress = true;
+ nir_metadata_preserve(function->impl, nir_metadata_none);
+ } else {
+ nir_metadata_preserve(function->impl, nir_metadata_all);
+ }
}
return progress;