Commit 5604c310 authored by Jason Ekstrand's avatar Jason Ekstrand Committed by Erik Faye-Lund

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's avatarKenneth Graunke <kenneth@whitecape.org>
parent 7a7ec410
...@@ -5739,6 +5739,7 @@ void visit_image_size(isel_context *ctx, nir_intrinsic_instr *instr) ...@@ -5739,6 +5739,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 */
......
...@@ -3078,6 +3078,7 @@ static LLVMValueRef visit_image_size(struct ac_nir_context *ctx, ...@@ -3078,6 +3078,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;
......
...@@ -1763,6 +1763,8 @@ ntq_emit_image_size(struct v3d_compile *c, nir_intrinsic_instr *instr) ...@@ -1763,6 +1763,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) {
......
...@@ -1317,6 +1317,11 @@ nir_visitor::visit(ir_call *ir) ...@@ -1317,6 +1317,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;
} }
......
...@@ -408,7 +408,7 @@ image("atomic_xor", src_comp=[4, 1, 1], dest_comp=1) ...@@ -408,7 +408,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=[1, 4, 1, 1], dest_comp=1) image("atomic_fadd", src_comp=[1, 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)
......
...@@ -3022,7 +3022,7 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, ...@@ -3022,7 +3022,7 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
switch (opcode) { switch (opcode) {
#define OP(S, N) case SpvOp##S: op = nir_intrinsic_image_deref_##N; break; #define OP(S, N) case SpvOp##S: op = nir_intrinsic_image_deref_##N; break;
OP(ImageQuerySize, size) OP(ImageQuerySize, size)
OP(ImageQuerySizeLod, size_lod) OP(ImageQuerySizeLod, size)
OP(ImageRead, load) OP(ImageRead, load)
OP(ImageWrite, store) OP(ImageWrite, store)
OP(AtomicLoad, load) OP(AtomicLoad, load)
...@@ -3085,13 +3085,15 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, ...@@ -3085,13 +3085,15 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
switch (opcode) { switch (opcode) {
case SpvOpImageQuerySize: case SpvOpImageQuerySize:
case SpvOpImageQueryFormat: intrin->src[1] = nir_src_for_ssa(nir_imm_int(&b->nb, 0));
case SpvOpImageQueryOrder:
/* No additional sources */
break; break;
case SpvOpImageQuerySizeLod: case SpvOpImageQuerySizeLod:
intrin->src[1] = nir_src_for_ssa(image.lod); intrin->src[1] = nir_src_for_ssa(image.lod);
break; break;
case SpvOpImageQueryFormat:
case SpvOpImageQueryOrder:
/* No additional sources */
break;
case SpvOpAtomicLoad: case SpvOpAtomicLoad:
case SpvOpImageRead: case SpvOpImageRead:
/* Only OpImageRead can support a lod parameter if /* Only OpImageRead can support a lod parameter if
......
...@@ -1220,6 +1220,7 @@ emit_intrinsic_image_size(struct ir3_context *ctx, nir_intrinsic_instr *intr, ...@@ -1220,6 +1220,7 @@ emit_intrinsic_image_size(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);
......
...@@ -2163,6 +2163,8 @@ Converter::visit(nir_intrinsic_instr *insn) ...@@ -2163,6 +2163,8 @@ Converter::visit(nir_intrinsic_instr *insn)
ty = TYPE_U32; ty = TYPE_U32;
break; break;
case nir_intrinsic_bindless_image_size: case nir_intrinsic_bindless_image_size:
case nir_intrinsic_image_size:
assert(nir_src_as_uint(insn->src[1]) == 0);
ty = TYPE_U32; ty = TYPE_U32;
break; break;
default: default:
......
...@@ -4265,6 +4265,8 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr ...@@ -4265,6 +4265,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;
......
...@@ -653,6 +653,8 @@ lower_image_size_instr(nir_builder *b, ...@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment