return type;
}
+static void
+vtn_handle_access_qualifier(struct vtn_builder *b, struct vtn_type *type,
+ int member, enum gl_access_qualifier access)
+{
+ type->members[member] = vtn_type_copy(b, type->members[member]);
+ type = type->members[member];
+
+ type->access |= access;
+}
+
static void
struct_member_decoration_cb(struct vtn_builder *b,
struct vtn_value *val, int member,
assert(member < ctx->num_fields);
switch (dec->decoration) {
+ case SpvDecorationRelaxedPrecision:
+ case SpvDecorationUniform:
+ break; /* FIXME: Do nothing with this for now. */
case SpvDecorationNonWritable:
+ vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_NON_WRITEABLE);
+ break;
case SpvDecorationNonReadable:
- case SpvDecorationRelaxedPrecision:
+ vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_NON_READABLE);
+ break;
case SpvDecorationVolatile:
+ vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_VOLATILE);
+ break;
case SpvDecorationCoherent:
- case SpvDecorationUniform:
- break; /* FIXME: Do nothing with this for now. */
+ vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_COHERENT);
+ break;
case SpvDecorationNoPerspective:
ctx->fields[member].interpolation = INTERP_MODE_NOPERSPECTIVE;
break;
struct vtn_access_chain *chain =
vtn_access_chain_extend(b, base->chain, deref_chain->length);
struct vtn_type *type = base->type;
+ enum gl_access_qualifier access = base->access;
/* OpPtrAccessChain is only allowed on things which support variable
* pointers. For everything else, the client is expected to just pass us
} else {
type = type->array_element;
}
+
+ access |= type->access;
}
struct vtn_pointer *ptr = rzalloc(b, struct vtn_pointer);
ptr->var = base->var;
ptr->deref = base->deref;
ptr->chain = chain;
+ ptr->access = access;
return ptr;
}
nir_ssa_def *block_index = base->block_index;
nir_ssa_def *offset = base->offset;
struct vtn_type *type = base->type;
+ enum gl_access_qualifier access = base->access;
unsigned idx = 0;
if (base->mode == vtn_variable_mode_ubo ||
idx++;
/* This consumes a level of type */
type = type->array_element;
+ access |= type->access;
} else {
/* This is annoying. We've been asked for a pointer to the
* array of UBOs/SSBOs and not a specifc buffer. Return a
vtn_access_link_as_ssa(b, deref_chain->link[idx], type->stride);
offset = nir_iadd(&b->nb, offset, elem_offset);
type = type->array_element;
+ access |= type->access;
break;
}
nir_ssa_def *mem_offset = nir_imm_int(&b->nb, type->offsets[member]);
offset = nir_iadd(&b->nb, offset, mem_offset);
type = type->members[member];
+ access |= type->access;
break;
}
ptr->type = type;
ptr->block_index = block_index;
ptr->offset = offset;
+ ptr->access = access;
return ptr;
}
vtn_assert(ptr_type->deref->type == var->type->type);
pointer->ptr_type = ptr_type;
pointer->var = var;
+ pointer->access = var->access | var->type->access;
return pointer;
}
_vtn_load_store_tail(struct vtn_builder *b, nir_intrinsic_op op, bool load,
nir_ssa_def *index, nir_ssa_def *offset,
unsigned access_offset, unsigned access_size,
- struct vtn_ssa_value **inout, const struct glsl_type *type)
+ struct vtn_ssa_value **inout, const struct glsl_type *type,
+ enum gl_access_qualifier access)
{
nir_intrinsic_instr *instr = nir_intrinsic_instr_create(b->nb.shader, op);
instr->num_components = glsl_get_vector_elements(type);
nir_intrinsic_set_range(instr, access_size);
}
+ if (op == nir_intrinsic_load_ssbo ||
+ op == nir_intrinsic_store_ssbo) {
+ nir_intrinsic_set_access(instr, access);
+ }
+
if (index)
instr->src[src++] = nir_src_for_ssa(index);
_vtn_block_load_store(struct vtn_builder *b, nir_intrinsic_op op, bool load,
nir_ssa_def *index, nir_ssa_def *offset,
unsigned access_offset, unsigned access_size,
- struct vtn_type *type, struct vtn_ssa_value **inout)
+ struct vtn_type *type, enum gl_access_qualifier access,
+ struct vtn_ssa_value **inout)
{
if (load && *inout == NULL)
*inout = vtn_create_ssa_value(b, type->type);
_vtn_load_store_tail(b, op, load, index, elem_offset,
access_offset, access_size,
&(*inout)->elems[i],
- glsl_vector_type(base_type, vec_width));
+ glsl_vector_type(base_type, vec_width),
+ type->access | access);
}
if (load && type->row_major)
vtn_assert(glsl_type_is_vector_or_scalar(type->type));
_vtn_load_store_tail(b, op, load, index, offset,
access_offset, access_size,
- inout, type->type);
+ inout, type->type,
+ type->access | access);
} else {
/* This is a strided load. We have to load N things separately.
* This is the single column of a row-major matrix case.
comp = &temp_val;
_vtn_load_store_tail(b, op, load, index, elem_offset,
access_offset, access_size,
- &comp, glsl_scalar_type(base_type));
+ &comp, glsl_scalar_type(base_type),
+ type->access | access);
per_comp[i] = comp->def;
}
nir_iadd(&b->nb, offset, nir_imm_int(&b->nb, i * type->stride));
_vtn_block_load_store(b, op, load, index, elem_off,
access_offset, access_size,
- type->array_element, &(*inout)->elems[i]);
+ type->array_element,
+ type->array_element->access | access,
+ &(*inout)->elems[i]);
}
return;
}
nir_iadd(&b->nb, offset, nir_imm_int(&b->nb, type->offsets[i]));
_vtn_block_load_store(b, op, load, index, elem_off,
access_offset, access_size,
- type->members[i], &(*inout)->elems[i]);
+ type->members[i],
+ type->members[i]->access | access,
+ &(*inout)->elems[i]);
}
return;
}
struct vtn_ssa_value *value = NULL;
_vtn_block_load_store(b, op, true, index, offset,
access_offset, access_size,
- src->type, &value);
+ src->type, src->access, &value);
return value;
}
offset = vtn_pointer_to_offset(b, dst, &index);
_vtn_block_load_store(b, op, false, index, offset,
- 0, 0, dst->type, &src);
+ 0, 0, dst->type, dst->access, &src);
}
static void
case SpvDecorationOffset:
vtn_var->offset = dec->literals[0];
break;
+ case SpvDecorationNonWritable:
+ vtn_var->access |= ACCESS_NON_WRITEABLE;
+ break;
+ case SpvDecorationNonReadable:
+ vtn_var->access |= ACCESS_NON_READABLE;
+ break;
+ case SpvDecorationVolatile:
+ vtn_var->access |= ACCESS_VOLATILE;
+ break;
+ case SpvDecorationCoherent:
+ vtn_var->access |= ACCESS_COHERENT;
+ break;
default:
break;
}