From 1ccd681109e80516430a3be489dca1be15316d50 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 19 Aug 2020 18:21:33 -0500 Subject: [PATCH] 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 Part-of: --- src/amd/compiler/aco_instruction_selection.cpp | 1 + src/amd/llvm/ac_nir_to_llvm.c | 1 + src/broadcom/compiler/nir_to_vir.c | 2 ++ src/compiler/glsl/glsl_to_nir.cpp | 5 +++++ src/compiler/nir/nir_intrinsics.py | 2 +- src/compiler/spirv/spirv_to_nir.c | 6 ++++-- src/freedreno/ir3/ir3_compiler_nir.c | 1 + src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp | 1 + src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp | 2 ++ src/intel/compiler/brw_fs_nir.cpp | 2 ++ src/intel/compiler/brw_nir_lower_image_load_store.c | 2 ++ 11 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index 07c61a33d81..7d45f5b8c33 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -6074,6 +6074,7 @@ void visit_image_size(isel_context *ctx, nir_intrinsic_instr *instr) } /* LOD */ + assert(nir_src_as_uint(instr->src[1]) == 0); Temp lod = bld.vop1(aco_opcode::v_mov_b32, bld.def(v1), Operand(0u)); /* Resource */ diff --git a/src/amd/llvm/ac_nir_to_llvm.c b/src/amd/llvm/ac_nir_to_llvm.c index 1b0bdffdb45..7643326fde5 100644 --- a/src/amd/llvm/ac_nir_to_llvm.c +++ b/src/amd/llvm/ac_nir_to_llvm.c @@ -3144,6 +3144,7 @@ static LLVMValueRef visit_image_size(struct ac_nir_context *ctx, args.dmask = 0xf; args.resource = get_image_descriptor(ctx, instr, dynamic_index, AC_DESC_IMAGE, false); args.opcode = ac_image_get_resinfo; + assert(nir_src_as_uint(instr->src[1]) == 0); args.lod = ctx->ac.i32_0; args.attributes = AC_FUNC_ATTR_READNONE; diff --git a/src/broadcom/compiler/nir_to_vir.c b/src/broadcom/compiler/nir_to_vir.c index 171028b627e..689414551e9 100644 --- a/src/broadcom/compiler/nir_to_vir.c +++ b/src/broadcom/compiler/nir_to_vir.c @@ -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]); bool is_array = nir_intrinsic_image_array(instr); + assert(nir_src_as_uint(instr->src[1]) == 0); + ntq_store_dest(c, &instr->dest, 0, vir_uniform(c, QUNIFORM_IMAGE_WIDTH, image_index)); if (instr->num_components > 1) { diff --git a/src/compiler/glsl/glsl_to_nir.cpp b/src/compiler/glsl/glsl_to_nir.cpp index 2dc0df32a93..6e8cfbecd0e 100644 --- a/src/compiler/glsl/glsl_to_nir.cpp +++ b/src/compiler/glsl/glsl_to_nir.cpp @@ -1338,6 +1338,11 @@ nir_visitor::visit(ir_call *ir) if (op == nir_intrinsic_image_deref_size || 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); break; } diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 2fa092d5f71..da4f95c5ed3 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -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_comp_swap", src_comp=[4, 1, 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("atomic_inc_wrap", src_comp=[4, 1, 1], dest_comp=1) image("atomic_dec_wrap", src_comp=[4, 1, 1], dest_comp=1) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 26c42fd46d8..604174bcaaa 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -3090,8 +3090,10 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, 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 * many. Swizzle to compensate. */ diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index 8d9d8ef18d1..a0f1a36545a 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -1219,6 +1219,7 @@ emit_intrinsic_image_size_tex(struct ir3_context *ctx, nir_intrinsic_instr *intr TYPE_U16 : TYPE_U32; info.flags |= flags; + assert(nir_src_as_uint(intr->src[1]) == 0); lod = create_immed(b, 0); sam = emit_sam(ctx, OPC_GETSIZE, info, dst_type, 0b1111, lod, NULL); diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp index dde73c20165..1df1c7753fd 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp @@ -2225,6 +2225,7 @@ Converter::visit(nir_intrinsic_instr *insn) break; case nir_intrinsic_bindless_image_size: case nir_intrinsic_image_size: + assert(nir_src_as_uint(insn->src[1]) == 0); ty = TYPE_U32; bindless = op == nir_intrinsic_bindless_image_size; break; diff --git a/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp b/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp index f5200405f7a..33f9022e82f 100644 --- a/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp @@ -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 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 dyn_offset = PValue(); int res_id = R600_IMAGE_REAL_RESOURCE_OFFSET; diff --git a/src/intel/compiler/brw_fs_nir.cpp b/src/intel/compiler/brw_fs_nir.cpp index f10525741f2..243ad37c4e3 100644 --- a/src/intel/compiler/brw_fs_nir.cpp +++ b/src/intel/compiler/brw_fs_nir.cpp @@ -4166,6 +4166,8 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr BRW_REGISTER_TYPE_UD); image = bld.emit_uniformize(image); + assert(nir_src_as_uint(instr->src[1]) == 0); + fs_reg srcs[TEX_LOGICAL_NUM_SRCS]; if (instr->intrinsic == nir_intrinsic_image_size) srcs[TEX_LOGICAL_SRC_SURFACE] = image; diff --git a/src/intel/compiler/brw_nir_lower_image_load_store.c b/src/intel/compiler/brw_nir_lower_image_load_store.c index 1825c2f0221..0c57b59fb93 100644 --- a/src/intel/compiler/brw_nir_lower_image_load_store.c +++ b/src/intel/compiler/brw_nir_lower_image_load_store.c @@ -653,6 +653,8 @@ lower_image_size_instr(nir_builder *b, 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); nir_ssa_def *size = load_image_param(b, deref, SIZE); -- 2.30.2