[Mesa-dev] [PATCH v2 40/73] ac/nir: add and use ac_shader_abi::load_sampler_desc
Nicolai Hähnle
nhaehnle at gmail.com
Wed Jul 5 10:48:24 UTC 2017
From: Nicolai Hähnle <nicolai.haehnle at 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 464d85d..b8d9296 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;
@@ -188,21 +181,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;
@@ -3296,21 +3290,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--;
@@ -3342,40 +3336,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;
@@ -3401,38 +3395,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;
@@ -3494,36 +3488,36 @@ static LLVMValueRef visit_image_atomic(struct nir_to_llvm_context *ctx,
break;
default:
abort();
}
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);
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; /* slc */
length = snprintf(intrinsic_name, sizeof(intrinsic_name),
"llvm.amdgcn.buffer.atomic.%s", atomic_name);
} else {
char coords_type[8];
bool da = glsl_sampler_type_is_array(type) ||
glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE;
LLVMValueRef 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 */
build_int_type_name(LLVMTypeOf(coords),
coords_type, sizeof(coords_type));
length = snprintf(intrinsic_name, sizeof(intrinsic_name),
"llvm.amdgcn.image.atomic.%s.%s", atomic_name, coords_type);
}
@@ -3537,27 +3531,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, "");
@@ -4109,76 +4103,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),
@@ -4193,20 +4178,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;
@@ -4263,34 +4274,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;
}
@@ -6124,20 +6135,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 1b204e9..63d31c8 100644
--- a/src/amd/common/ac_shader_abi.h
+++ b/src/amd/common/ac_shader_abi.h
@@ -19,20 +19,27 @@
* 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
#include <llvm-c/Core.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;
LLVMValueRef base_vertex;
LLVMValueRef start_instance;
LLVMValueRef draw_id;
LLVMValueRef vertex_id;
@@ -43,13 +50,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
More information about the mesa-dev
mailing list