From 364996d70dec716707493d667e17d2c1efcb7259 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Tue, 4 Jun 2019 11:41:25 +0200 Subject: [PATCH] glsl/nir: Propagate access qualifiers We were completely ignoring these before, except for putting them on variables. While we're here, don't set access qualifiers when converting to bindless since glsl_to_nir will already have set a more accurate qualifier that includes any qualifiers on struct members that are dereferenced. Reviewed-by: Timothy Arceri --- src/compiler/glsl/glsl_to_nir.cpp | 64 ++++++++++++++++++++++++++++--- src/compiler/nir/nir.c | 1 - 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/compiler/glsl/glsl_to_nir.cpp b/src/compiler/glsl/glsl_to_nir.cpp index 2e0075c2d5e..656566e4c61 100644 --- a/src/compiler/glsl/glsl_to_nir.cpp +++ b/src/compiler/glsl/glsl_to_nir.cpp @@ -34,6 +34,7 @@ #include "program.h" #include "compiler/nir/nir_control_flow.h" #include "compiler/nir/nir_builder.h" +#include "compiler/nir/nir_deref.h" #include "main/errors.h" #include "main/imports.h" #include "main/mtypes.h" @@ -812,6 +813,45 @@ intrinsic_set_std430_align(nir_intrinsic_instr *intrin, const glsl_type *type) nir_intrinsic_set_align(intrin, (bit_size / 8) * pow2_components, 0); } +/* Accumulate any qualifiers along the deref chain to get the actual + * load/store qualifier. + */ + +static enum gl_access_qualifier +deref_get_qualifier(nir_deref_instr *deref) +{ + nir_deref_path path; + nir_deref_path_init(&path, deref, NULL); + + unsigned qualifiers = path.path[0]->var->data.image.access; + + const glsl_type *parent_type = path.path[0]->type; + for (nir_deref_instr **cur_ptr = &path.path[1]; *cur_ptr; cur_ptr++) { + nir_deref_instr *cur = *cur_ptr; + + if (parent_type->is_interface()) { + const struct glsl_struct_field *field = + &parent_type->fields.structure[cur->strct.index]; + if (field->memory_read_only) + qualifiers |= ACCESS_NON_WRITEABLE; + if (field->memory_write_only) + qualifiers |= ACCESS_NON_READABLE; + if (field->memory_coherent) + qualifiers |= ACCESS_COHERENT; + if (field->memory_volatile) + qualifiers |= ACCESS_VOLATILE; + if (field->memory_restrict) + qualifiers |= ACCESS_RESTRICT; + } + + parent_type = cur->type; + } + + nir_deref_path_finish(&path); + + return (gl_access_qualifier) qualifiers; +} + void nir_visitor::visit(ir_call *ir) { @@ -1121,6 +1161,8 @@ nir_visitor::visit(ir_call *ir) } instr->src[0] = nir_src_for_ssa(&nir_deref->dest.ssa); + nir_intrinsic_set_access(instr, deref_get_qualifier(nir_deref)); + /* data1 parameter (this is always present) */ param = param->get_next(); ir_instruction *inst = (ir_instruction *) param; @@ -1204,6 +1246,8 @@ nir_visitor::visit(ir_call *ir) nir_deref_instr *deref = evaluate_deref(image); const glsl_type *type = deref->type; + nir_intrinsic_set_access(instr, deref_get_qualifier(deref)); + instr->src[0] = nir_src_for_ssa(&deref->dest.ssa); param = param->get_next(); @@ -1607,12 +1651,18 @@ nir_visitor::visit(ir_assignment *ir) if ((ir->rhs->as_dereference() || ir->rhs->as_constant()) && (ir->write_mask == (1 << num_components) - 1 || ir->write_mask == 0)) { + nir_deref_instr *lhs = evaluate_deref(ir->lhs); + nir_deref_instr *rhs = evaluate_deref(ir->rhs); + enum gl_access_qualifier lhs_qualifiers = deref_get_qualifier(lhs); + enum gl_access_qualifier rhs_qualifiers = deref_get_qualifier(rhs); if (ir->condition) { nir_push_if(&b, evaluate_rvalue(ir->condition)); - nir_copy_deref(&b, evaluate_deref(ir->lhs), evaluate_deref(ir->rhs)); + nir_copy_deref_with_access(&b, lhs, rhs, lhs_qualifiers, + rhs_qualifiers); nir_pop_if(&b, NULL); } else { - nir_copy_deref(&b, evaluate_deref(ir->lhs), evaluate_deref(ir->rhs)); + nir_copy_deref_with_access(&b, lhs, rhs, lhs_qualifiers, + rhs_qualifiers); } return; } @@ -1637,12 +1687,15 @@ nir_visitor::visit(ir_assignment *ir) src = nir_swizzle(&b, src, swiz, num_components); } + enum gl_access_qualifier qualifiers = deref_get_qualifier(lhs_deref); if (ir->condition) { nir_push_if(&b, evaluate_rvalue(ir->condition)); - nir_store_deref(&b, lhs_deref, src, ir->write_mask); + nir_store_deref_with_access(&b, lhs_deref, src, ir->write_mask, + qualifiers); nir_pop_if(&b, NULL); } else { - nir_store_deref(&b, lhs_deref, src, ir->write_mask); + nir_store_deref_with_access(&b, lhs_deref, src, ir->write_mask, + qualifiers); } } @@ -1709,7 +1762,8 @@ nir_visitor::evaluate_rvalue(ir_rvalue* ir) * must emit a variable load. */ - this->result = nir_load_deref(&b, this->deref); + enum gl_access_qualifier access = deref_get_qualifier(this->deref); + this->result = nir_load_deref_with_access(&b, this->deref, access); } return this->result; diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index 524b9445b11..81f569b4c2b 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -2041,7 +2041,6 @@ nir_rewrite_image_intrinsic(nir_intrinsic_instr *intrin, nir_ssa_def *src, nir_intrinsic_set_image_dim(intrin, glsl_get_sampler_dim(deref->type)); nir_intrinsic_set_image_array(intrin, glsl_sampler_type_is_array(deref->type)); - nir_intrinsic_set_access(intrin, var->data.image.access); nir_intrinsic_set_format(intrin, var->data.image.format); nir_instr_rewrite_src(&intrin->instr, &intrin->src[0], -- 2.30.2