nir: Add an LOD parameter to image_*_size

The OpenCL image_width/height/depth functions have variants which can
take an LOD parameter.  More importantly, LLVM-SPIRV-Translator always
generates OpImageQuerySizeLod even if the LOD is guaranteed to be zero.
Given that over half the hardware out there has an LOD field for image
size queries (based on a rudimentary scan through their NIR -> whatever
code), we may as well just add the source to the NIR intrinsic.  If this
is ever a problem for anyone, the lowering is pretty trivial.

I've also added asserts to everyone's drivers that should alert them if
they ever see an LOD other than zero.  This will never happen with GL or
Vulkan so there's no need for panic.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6396>
This commit is contained in:
Jason Ekstrand
2020-08-19 18:21:33 -05:00
committed by Marge Bot
parent a104902590
commit 1ccd681109
11 changed files with 22 additions and 3 deletions

View File

@@ -6074,6 +6074,7 @@ void visit_image_size(isel_context *ctx, nir_intrinsic_instr *instr)
} }
/* LOD */ /* LOD */
assert(nir_src_as_uint(instr->src[1]) == 0);
Temp lod = bld.vop1(aco_opcode::v_mov_b32, bld.def(v1), Operand(0u)); Temp lod = bld.vop1(aco_opcode::v_mov_b32, bld.def(v1), Operand(0u));
/* Resource */ /* Resource */

View File

@@ -3144,6 +3144,7 @@ static LLVMValueRef visit_image_size(struct ac_nir_context *ctx,
args.dmask = 0xf; args.dmask = 0xf;
args.resource = get_image_descriptor(ctx, instr, dynamic_index, AC_DESC_IMAGE, false); args.resource = get_image_descriptor(ctx, instr, dynamic_index, AC_DESC_IMAGE, false);
args.opcode = ac_image_get_resinfo; args.opcode = ac_image_get_resinfo;
assert(nir_src_as_uint(instr->src[1]) == 0);
args.lod = ctx->ac.i32_0; args.lod = ctx->ac.i32_0;
args.attributes = AC_FUNC_ATTR_READNONE; args.attributes = AC_FUNC_ATTR_READNONE;

View File

@@ -1780,6 +1780,8 @@ ntq_emit_image_size(struct v3d_compile *c, nir_intrinsic_instr *instr)
unsigned image_index = nir_src_as_uint(instr->src[0]); unsigned image_index = nir_src_as_uint(instr->src[0]);
bool is_array = nir_intrinsic_image_array(instr); bool is_array = nir_intrinsic_image_array(instr);
assert(nir_src_as_uint(instr->src[1]) == 0);
ntq_store_dest(c, &instr->dest, 0, ntq_store_dest(c, &instr->dest, 0,
vir_uniform(c, QUNIFORM_IMAGE_WIDTH, image_index)); vir_uniform(c, QUNIFORM_IMAGE_WIDTH, image_index));
if (instr->num_components > 1) { if (instr->num_components > 1) {

View File

@@ -1338,6 +1338,11 @@ nir_visitor::visit(ir_call *ir)
if (op == nir_intrinsic_image_deref_size || if (op == nir_intrinsic_image_deref_size ||
op == nir_intrinsic_image_deref_samples) { op == nir_intrinsic_image_deref_samples) {
/* image_deref_size takes an LOD parameter which is always 0
* coming from GLSL.
*/
if (op == nir_intrinsic_image_deref_size)
instr->src[1] = nir_src_for_ssa(nir_imm_int(&b, 0));
nir_builder_instr_insert(&b, &instr->instr); nir_builder_instr_insert(&b, &instr->instr);
break; break;
} }

View File

@@ -406,7 +406,7 @@ image("atomic_xor", src_comp=[4, 1, 1], dest_comp=1)
image("atomic_exchange", src_comp=[4, 1, 1], dest_comp=1) image("atomic_exchange", src_comp=[4, 1, 1], dest_comp=1)
image("atomic_comp_swap", src_comp=[4, 1, 1, 1], dest_comp=1) image("atomic_comp_swap", src_comp=[4, 1, 1, 1], dest_comp=1)
image("atomic_fadd", src_comp=[4, 1, 1], dest_comp=1) image("atomic_fadd", src_comp=[4, 1, 1], dest_comp=1)
image("size", dest_comp=0, flags=[CAN_ELIMINATE, CAN_REORDER]) image("size", dest_comp=0, src_comp=[1], flags=[CAN_ELIMINATE, CAN_REORDER])
image("samples", dest_comp=1, flags=[CAN_ELIMINATE, CAN_REORDER]) image("samples", dest_comp=1, flags=[CAN_ELIMINATE, CAN_REORDER])
image("atomic_inc_wrap", src_comp=[4, 1, 1], dest_comp=1) image("atomic_inc_wrap", src_comp=[4, 1, 1], dest_comp=1)
image("atomic_dec_wrap", src_comp=[4, 1, 1], dest_comp=1) image("atomic_dec_wrap", src_comp=[4, 1, 1], dest_comp=1)

View File

@@ -3090,8 +3090,10 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
intrin->src[0] = nir_src_for_ssa(&image.image->dest.ssa); intrin->src[0] = nir_src_for_ssa(&image.image->dest.ssa);
/* ImageQuerySize doesn't take any extra parameters */ if (opcode == SpvOpImageQuerySize) {
if (opcode != SpvOpImageQuerySize) { /* ImageQuerySize only has an LOD which is currently always 0 */
intrin->src[1] = nir_src_for_ssa(nir_imm_int(&b->nb, 0));
} else {
/* The image coordinate is always 4 components but we may not have that /* The image coordinate is always 4 components but we may not have that
* many. Swizzle to compensate. * many. Swizzle to compensate.
*/ */

View File

@@ -1219,6 +1219,7 @@ emit_intrinsic_image_size_tex(struct ir3_context *ctx, nir_intrinsic_instr *intr
TYPE_U16 : TYPE_U32; TYPE_U16 : TYPE_U32;
info.flags |= flags; info.flags |= flags;
assert(nir_src_as_uint(intr->src[1]) == 0);
lod = create_immed(b, 0); lod = create_immed(b, 0);
sam = emit_sam(ctx, OPC_GETSIZE, info, dst_type, 0b1111, lod, NULL); sam = emit_sam(ctx, OPC_GETSIZE, info, dst_type, 0b1111, lod, NULL);

View File

@@ -2225,6 +2225,7 @@ Converter::visit(nir_intrinsic_instr *insn)
break; break;
case nir_intrinsic_bindless_image_size: case nir_intrinsic_bindless_image_size:
case nir_intrinsic_image_size: case nir_intrinsic_image_size:
assert(nir_src_as_uint(insn->src[1]) == 0);
ty = TYPE_U32; ty = TYPE_U32;
bindless = op == nir_intrinsic_bindless_image_size; bindless = op == nir_intrinsic_bindless_image_size;
break; break;

View File

@@ -557,6 +557,8 @@ bool EmitSSBOInstruction::emit_image_size(const nir_intrinsic_instr *intrin)
GPRVector dest = vec_from_nir(intrin->dest, nir_dest_num_components(intrin->dest)); GPRVector dest = vec_from_nir(intrin->dest, nir_dest_num_components(intrin->dest));
GPRVector src{0,{4,4,4,4}}; GPRVector src{0,{4,4,4,4}};
assert(nir_src_as_uint(intrin->src[1]) == 0);
auto const_offset = nir_src_as_const_value(intrin->src[0]); auto const_offset = nir_src_as_const_value(intrin->src[0]);
auto dyn_offset = PValue(); auto dyn_offset = PValue();
int res_id = R600_IMAGE_REAL_RESOURCE_OFFSET; int res_id = R600_IMAGE_REAL_RESOURCE_OFFSET;

View File

@@ -4166,6 +4166,8 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
BRW_REGISTER_TYPE_UD); BRW_REGISTER_TYPE_UD);
image = bld.emit_uniformize(image); image = bld.emit_uniformize(image);
assert(nir_src_as_uint(instr->src[1]) == 0);
fs_reg srcs[TEX_LOGICAL_NUM_SRCS]; fs_reg srcs[TEX_LOGICAL_NUM_SRCS];
if (instr->intrinsic == nir_intrinsic_image_size) if (instr->intrinsic == nir_intrinsic_image_size)
srcs[TEX_LOGICAL_SRC_SURFACE] = image; srcs[TEX_LOGICAL_SRC_SURFACE] = image;

View File

@@ -653,6 +653,8 @@ lower_image_size_instr(nir_builder *b,
if (isl_has_matching_typed_storage_image_format(devinfo, image_fmt)) if (isl_has_matching_typed_storage_image_format(devinfo, image_fmt))
return false; return false;
assert(nir_src_as_uint(intrin->src[1]) == 0);
b->cursor = nir_instr_remove(&intrin->instr); b->cursor = nir_instr_remove(&intrin->instr);
nir_ssa_def *size = load_image_param(b, deref, SIZE); nir_ssa_def *size = load_image_param(b, deref, SIZE);