From: Nicolai Hähnle <nicolai.haeh...@amd.com> --- src/amd/common/ac_nir_to_llvm.c | 108 ++++++++++++++++++++++------------------ src/amd/common/ac_shader_abi.h | 24 +++++++++ 2 files changed, 84 insertions(+), 48 deletions(-)
diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c index 5e85408..fa681a8 100644 --- a/src/amd/common/ac_nir_to_llvm.c +++ b/src/amd/common/ac_nir_to_llvm.c @@ -40,27 +40,20 @@ enum radeon_llvm_calling_convention { RADEON_LLVM_AMDGPU_PS = 89, RADEON_LLVM_AMDGPU_CS = 90, }; #define CONST_ADDR_SPACE 2 #define LOCAL_ADDR_SPACE 3 #define RADEON_LLVM_MAX_INPUTS (VARYING_SLOT_VAR31 + 1) #define RADEON_LLVM_MAX_OUTPUTS (VARYING_SLOT_VAR31 + 1) -enum desc_type { - DESC_IMAGE, - DESC_FMASK, - DESC_SAMPLER, - DESC_BUFFER, -}; - struct nir_to_llvm_context; struct ac_nir_context { struct ac_llvm_context ac; struct ac_shader_abi *abi; gl_shader_stage stage; struct hash_table *defs; struct hash_table *phis; @@ -190,21 +183,22 @@ struct nir_to_llvm_context { static inline struct nir_to_llvm_context * nir_to_llvm_context_from_abi(struct ac_shader_abi *abi) { struct nir_to_llvm_context *ctx = NULL; return container_of(abi, ctx, abi); } static LLVMValueRef get_sampler_desc(struct nir_to_llvm_context *ctx, const nir_deref_var *deref, - enum desc_type desc_type); + enum ac_descriptor_type desc_type); + static unsigned radeon_llvm_reg_index_soa(unsigned index, unsigned chan) { return (index * 4) + chan; } static unsigned shader_io_get_unique_index(gl_varying_slot slot) { /* handle patch indices separate */ if (slot == VARYING_SLOT_TESS_LEVEL_OUTER) return 0; @@ -3229,21 +3223,21 @@ static LLVMValueRef get_image_coords(struct nir_to_llvm_context *ctx, fmask_load_address[2] = NULL; if (add_frag_pos) { for (chan = 0; chan < 2; ++chan) fmask_load_address[chan] = LLVMBuildAdd(ctx->builder, fmask_load_address[chan], LLVMBuildFPToUI(ctx->builder, ctx->frag_pos[chan], ctx->i32, ""), ""); } sample_index = adjust_sample_index_using_fmask(&ctx->ac, fmask_load_address[0], fmask_load_address[1], fmask_load_address[2], sample_index, - get_sampler_desc(ctx, instr->variables[0], DESC_FMASK)); + get_sampler_desc(ctx, instr->variables[0], AC_DESC_FMASK)); } if (count == 1) { if (instr->src[0].ssa->num_components) res = LLVMBuildExtractElement(ctx->builder, src0, masks[0], ""); else res = src0; } else { int chan; if (is_ms) count--; @@ -3275,40 +3269,40 @@ static LLVMValueRef visit_image_load(struct nir_to_llvm_context *ctx, LLVMValueRef params[7]; LLVMValueRef res; char intrinsic_name[64]; const nir_variable *var = instr->variables[0]->var; const struct glsl_type *type = var->type; if(instr->variables[0]->deref.child) type = instr->variables[0]->deref.child->type; type = glsl_without_array(type); if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_BUF) { - params[0] = get_sampler_desc(ctx, instr->variables[0], DESC_BUFFER); + params[0] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_BUFFER); params[1] = LLVMBuildExtractElement(ctx->builder, get_src(ctx->nir, instr->src[0]), LLVMConstInt(ctx->i32, 0, false), ""); /* vindex */ params[2] = LLVMConstInt(ctx->i32, 0, false); /* voffset */ params[3] = ctx->i1false; /* glc */ params[4] = ctx->i1false; /* slc */ res = ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.buffer.load.format.v4f32", ctx->v4f32, params, 5, 0); res = trim_vector(&ctx->ac, res, instr->dest.ssa.num_components); res = to_integer(&ctx->ac, res); } else { bool is_da = glsl_sampler_type_is_array(type) || glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE; LLVMValueRef da = is_da ? ctx->i1true : ctx->i1false; LLVMValueRef glc = ctx->i1false; LLVMValueRef slc = ctx->i1false; params[0] = get_image_coords(ctx, instr); - params[1] = get_sampler_desc(ctx, instr->variables[0], DESC_IMAGE); + params[1] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_IMAGE); params[2] = LLVMConstInt(ctx->i32, 15, false); /* dmask */ if (HAVE_LLVM <= 0x0309) { params[3] = ctx->i1false; /* r128 */ params[4] = da; params[5] = glc; params[6] = slc; } else { LLVMValueRef lwe = ctx->i1false; params[3] = glc; params[4] = slc; @@ -3334,38 +3328,38 @@ static void visit_image_store(struct nir_to_llvm_context *ctx, LLVMValueRef params[8]; char intrinsic_name[64]; const nir_variable *var = instr->variables[0]->var; const struct glsl_type *type = glsl_without_array(var->type); if (ctx->stage == MESA_SHADER_FRAGMENT) ctx->shader_info->fs.writes_memory = true; if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_BUF) { params[0] = to_float(&ctx->ac, get_src(ctx->nir, instr->src[2])); /* data */ - params[1] = get_sampler_desc(ctx, instr->variables[0], DESC_BUFFER); + params[1] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_BUFFER); params[2] = LLVMBuildExtractElement(ctx->builder, get_src(ctx->nir, instr->src[0]), LLVMConstInt(ctx->i32, 0, false), ""); /* vindex */ params[3] = LLVMConstInt(ctx->i32, 0, false); /* voffset */ params[4] = ctx->i1false; /* glc */ params[5] = ctx->i1false; /* slc */ ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.buffer.store.format.v4f32", ctx->voidt, params, 6, 0); } else { bool is_da = glsl_sampler_type_is_array(type) || glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE; LLVMValueRef da = is_da ? ctx->i1true : ctx->i1false; LLVMValueRef glc = ctx->i1false; LLVMValueRef slc = ctx->i1false; params[0] = to_float(&ctx->ac, get_src(ctx->nir, instr->src[2])); params[1] = get_image_coords(ctx, instr); /* coords */ - params[2] = get_sampler_desc(ctx, instr->variables[0], DESC_IMAGE); + params[2] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_IMAGE); params[3] = LLVMConstInt(ctx->i32, 15, false); /* dmask */ if (HAVE_LLVM <= 0x0309) { params[4] = ctx->i1false; /* r128 */ params[5] = da; params[6] = glc; params[7] = slc; } else { LLVMValueRef lwe = ctx->i1false; params[4] = glc; params[5] = slc; @@ -3399,32 +3393,32 @@ static LLVMValueRef visit_image_atomic(struct nir_to_llvm_context *ctx, const struct glsl_type *type = glsl_without_array(var->type); if (ctx->stage == MESA_SHADER_FRAGMENT) ctx->shader_info->fs.writes_memory = true; params[param_count++] = get_src(ctx->nir, instr->src[2]); if (instr->intrinsic == nir_intrinsic_image_atomic_comp_swap) params[param_count++] = get_src(ctx->nir, instr->src[3]); if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_BUF) { - params[param_count++] = get_sampler_desc(ctx, instr->variables[0], DESC_BUFFER); + params[param_count++] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_BUFFER); coords = params[param_count++] = LLVMBuildExtractElement(ctx->builder, get_src(ctx->nir, instr->src[0]), LLVMConstInt(ctx->i32, 0, false), ""); /* vindex */ params[param_count++] = ctx->i32zero; /* voffset */ params[param_count++] = ctx->i1false; /* glc */ params[param_count++] = ctx->i1false; /* slc */ } else { bool da = glsl_sampler_type_is_array(type) || glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE; coords = params[param_count++] = get_image_coords(ctx, instr); - params[param_count++] = get_sampler_desc(ctx, instr->variables[0], DESC_IMAGE); + params[param_count++] = get_sampler_desc(ctx, instr->variables[0], AC_DESC_IMAGE); params[param_count++] = ctx->i1false; /* r128 */ params[param_count++] = da ? ctx->i1true : ctx->i1false; /* da */ params[param_count++] = ctx->i1false; /* slc */ } switch (instr->intrinsic) { case nir_intrinsic_image_atomic_add: atomic_name = "add"; break; case nir_intrinsic_image_atomic_min: @@ -3464,27 +3458,27 @@ static LLVMValueRef visit_image_size(struct ac_nir_context *ctx, { LLVMValueRef res; const nir_variable *var = instr->variables[0]->var; const struct glsl_type *type = instr->variables[0]->var->type; bool da = glsl_sampler_type_is_array(var->type) || glsl_get_sampler_dim(var->type) == GLSL_SAMPLER_DIM_CUBE; if(instr->variables[0]->deref.child) type = instr->variables[0]->deref.child->type; if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_BUF) - return get_buffer_size(ctx, get_sampler_desc(ctx->nctx, instr->variables[0], DESC_BUFFER), true); + return get_buffer_size(ctx, get_sampler_desc(ctx->nctx, instr->variables[0], AC_DESC_BUFFER), true); struct ac_image_args args = { 0 }; args.da = da; args.dmask = 0xf; - args.resource = get_sampler_desc(ctx->nctx, instr->variables[0], DESC_IMAGE); + args.resource = get_sampler_desc(ctx->nctx, instr->variables[0], AC_DESC_IMAGE); args.opcode = ac_image_get_resinfo; args.addr = ctx->ac.i32_0; res = ac_build_image_opcode(&ctx->ac, &args); if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE && glsl_sampler_type_is_array(type)) { LLVMValueRef two = LLVMConstInt(ctx->ac.i32, 2, false); LLVMValueRef six = LLVMConstInt(ctx->ac.i32, 6, false); LLVMValueRef z = LLVMBuildExtractElement(ctx->ac.builder, res, two, ""); @@ -4033,76 +4027,67 @@ static void visit_intrinsic(struct ac_nir_context *ctx, fprintf(stderr, "Unknown intrinsic: "); nir_print_instr(&instr->instr, stderr); fprintf(stderr, "\n"); break; } if (result) { _mesa_hash_table_insert(ctx->defs, &instr->dest.ssa, result); } } -static LLVMValueRef get_sampler_desc(struct nir_to_llvm_context *ctx, - const nir_deref_var *deref, - enum desc_type desc_type) +static LLVMValueRef radv_get_sampler_desc(struct ac_shader_abi *abi, + unsigned descriptor_set, + unsigned base_index, + unsigned constant_index, + LLVMValueRef index, + enum ac_descriptor_type desc_type) { - unsigned desc_set = deref->var->data.descriptor_set; - LLVMValueRef list = ctx->descriptor_sets[desc_set]; - struct radv_descriptor_set_layout *layout = ctx->options->layout->set[desc_set].layout; - struct radv_descriptor_set_binding_layout *binding = layout->binding + deref->var->data.binding; + struct nir_to_llvm_context *ctx = nir_to_llvm_context_from_abi(abi); + LLVMValueRef list = ctx->descriptor_sets[descriptor_set]; + struct radv_descriptor_set_layout *layout = ctx->options->layout->set[descriptor_set].layout; + struct radv_descriptor_set_binding_layout *binding = layout->binding + base_index; unsigned offset = binding->offset; unsigned stride = binding->size; unsigned type_size; LLVMBuilderRef builder = ctx->builder; LLVMTypeRef type; - LLVMValueRef index = NULL; - unsigned constant_index = 0; - assert(deref->var->data.binding < layout->binding_count); + assert(base_index < layout->binding_count); switch (desc_type) { - case DESC_IMAGE: + case AC_DESC_IMAGE: type = ctx->v8i32; type_size = 32; break; - case DESC_FMASK: + case AC_DESC_FMASK: type = ctx->v8i32; offset += 32; type_size = 32; break; - case DESC_SAMPLER: + case AC_DESC_SAMPLER: type = ctx->v4i32; if (binding->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) offset += 64; type_size = 16; break; - case DESC_BUFFER: + case AC_DESC_BUFFER: type = ctx->v4i32; type_size = 16; break; default: unreachable("invalid desc_type\n"); } - if (deref->deref.child) { - const nir_deref_array *child = - (const nir_deref_array *)deref->deref.child; + offset += constant_index * stride; - assert(child->deref_array_type != nir_deref_array_type_wildcard); - offset += child->base_offset * stride; - if (child->deref_array_type == nir_deref_array_type_indirect) { - index = get_src(ctx->nir, child->indirect); - } - - constant_index = child->base_offset; - } - if (desc_type == DESC_SAMPLER && binding->immutable_samplers_offset && + if (desc_type == AC_DESC_SAMPLER && binding->immutable_samplers_offset && (!index || binding->immutable_samplers_equal)) { if (binding->immutable_samplers_equal) constant_index = 0; const uint32_t *samplers = radv_immutable_samplers(layout, binding); LLVMValueRef constants[] = { LLVMConstInt(ctx->i32, samplers[constant_index * 4 + 0], 0), LLVMConstInt(ctx->i32, samplers[constant_index * 4 + 1], 0), LLVMConstInt(ctx->i32, samplers[constant_index * 4 + 2], 0), @@ -4117,20 +4102,46 @@ static LLVMValueRef get_sampler_desc(struct nir_to_llvm_context *ctx, index = ctx->i32zero; index = LLVMBuildMul(builder, index, LLVMConstInt(ctx->i32, stride / type_size, 0), ""); list = ac_build_gep0(&ctx->ac, list, LLVMConstInt(ctx->i32, offset, 0)); list = LLVMBuildPointerCast(builder, list, const_array(type, 0), ""); return ac_build_indexed_load_const(&ctx->ac, list, index); } +static LLVMValueRef get_sampler_desc(struct nir_to_llvm_context *ctx, + const nir_deref_var *deref, + enum ac_descriptor_type desc_type) +{ + LLVMValueRef index = NULL; + unsigned constant_index = 0; + + if (deref->deref.child) { + const nir_deref_array *child = + (const nir_deref_array *)deref->deref.child; + + assert(child->deref_array_type != nir_deref_array_type_wildcard); + if (child->deref_array_type == nir_deref_array_type_indirect) { + index = get_src(ctx->nir, child->indirect); + } + + constant_index = child->base_offset; + } + + return ctx->abi.load_sampler_desc(&ctx->abi, + deref->var->data.descriptor_set, + deref->var->data.binding, + constant_index, index, + desc_type); +} + static void set_tex_fetch_args(struct ac_llvm_context *ctx, struct ac_image_args *args, const nir_tex_instr *instr, nir_texop op, LLVMValueRef res_ptr, LLVMValueRef samp_ptr, LLVMValueRef *param, unsigned count, unsigned dmask) { unsigned is_rect = 0; bool da = instr->is_array || instr->sampler_dim == GLSL_SAMPLER_DIM_CUBE; @@ -4187,34 +4198,34 @@ static LLVMValueRef sici_fix_sampler_aniso(struct nir_to_llvm_context *ctx, return LLVMBuildInsertElement(builder, samp, samp0, LLVMConstInt(ctx->i32, 0, 0), ""); } static void tex_fetch_ptrs(struct nir_to_llvm_context *ctx, nir_tex_instr *instr, LLVMValueRef *res_ptr, LLVMValueRef *samp_ptr, LLVMValueRef *fmask_ptr) { if (instr->sampler_dim == GLSL_SAMPLER_DIM_BUF) - *res_ptr = get_sampler_desc(ctx, instr->texture, DESC_BUFFER); + *res_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_BUFFER); else - *res_ptr = get_sampler_desc(ctx, instr->texture, DESC_IMAGE); + *res_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_IMAGE); if (samp_ptr) { if (instr->sampler) - *samp_ptr = get_sampler_desc(ctx, instr->sampler, DESC_SAMPLER); + *samp_ptr = get_sampler_desc(ctx, instr->sampler, AC_DESC_SAMPLER); else - *samp_ptr = get_sampler_desc(ctx, instr->texture, DESC_SAMPLER); + *samp_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_SAMPLER); if (instr->sampler_dim < GLSL_SAMPLER_DIM_RECT) *samp_ptr = sici_fix_sampler_aniso(ctx, *res_ptr, *samp_ptr); } if (fmask_ptr && !instr->sampler && (instr->op == nir_texop_txf_ms || instr->op == nir_texop_samples_identical)) - *fmask_ptr = get_sampler_desc(ctx, instr->texture, DESC_FMASK); + *fmask_ptr = get_sampler_desc(ctx, instr->texture, AC_DESC_FMASK); } static LLVMValueRef apply_round_slice(struct ac_llvm_context *ctx, LLVMValueRef coord) { coord = to_float(ctx, coord); coord = ac_build_intrinsic(ctx, "llvm.rint.f32", ctx->f32, &coord, 1, 0); coord = to_integer(ctx, coord); return coord; } @@ -6033,20 +6044,21 @@ LLVMModuleRef ac_translate_nir_to_llvm(LLVMTargetMachineRef tm, nir_foreach_variable(variable, &nir->inputs) handle_shader_input_decl(&ctx, variable); if (nir->stage == MESA_SHADER_FRAGMENT) handle_fs_inputs_pre(&ctx, nir); ctx.abi.chip_class = options->chip_class; ctx.abi.inputs = &ctx.inputs[0]; ctx.abi.emit_outputs = handle_shader_outputs_post; + ctx.abi.load_sampler_desc = radv_get_sampler_desc; nir_foreach_variable(variable, &nir->outputs) scan_shader_output_decl(&ctx, variable); ac_nir_translate(&ctx.ac, &ctx.abi, nir, &ctx); LLVMBuildRetVoid(ctx.builder); ac_llvm_finalize_module(&ctx); diff --git a/src/amd/common/ac_shader_abi.h b/src/amd/common/ac_shader_abi.h index 5d66656..c0cdfec 100644 --- a/src/amd/common/ac_shader_abi.h +++ b/src/amd/common/ac_shader_abi.h @@ -17,20 +17,27 @@ * 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. */ #ifndef AC_SHADER_ABI_H #define AC_SHADER_ABI_H +enum ac_descriptor_type { + AC_DESC_IMAGE, + AC_DESC_FMASK, + AC_DESC_SAMPLER, + AC_DESC_BUFFER, +}; + /* Document the shader ABI during compilation. This is what allows radeonsi and * radv to share a compiler backend. */ struct ac_shader_abi { enum chip_class chip_class; int param_base_vertex; int param_start_instance; int param_draw_id; int param_vertex_id; @@ -41,13 +48,30 @@ struct ac_shader_abi { * Currently only used for NIR shaders; indexed by variables' * driver_location. */ LLVMValueRef *inputs; void (*emit_outputs)(struct ac_shader_abi *abi, unsigned max_outputs, LLVMValueRef *addrs); LLVMValueRef (*load_ubo)(struct ac_shader_abi *abi, LLVMValueRef index); + + /** + * Load a descriptor associated to a sampler. + * + * \param descriptor_set the descriptor set index (only for Vulkan) + * \param base_index the base index of the sampler variable + * \param constant_index constant part of an array index (or 0, if the + * sampler variable is not an array) + * \param index non-constant part of an array index (may be NULL) + * \param desc_type the type of descriptor to load + */ + LLVMValueRef (*load_sampler_desc)(struct ac_shader_abi *abi, + unsigned descriptor_set, + unsigned base_index, + unsigned constant_index, + LLVMValueRef index, + enum ac_descriptor_type desc_type); }; #endif /* AC_SHADER_ABI_H */ -- 2.9.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev