nir_ssa_def *ssa = vtn_ssa_value(b, link.id)->def;
if (ssa->bit_size != bit_size)
ssa = nir_i2i(&b->nb, ssa, bit_size);
- if (stride != 1)
- ssa = nir_imul_imm(&b->nb, ssa, stride);
- return ssa;
+ return nir_imul_imm(&b->nb, ssa, stride);
}
}
nir_ssa_def *desc_array_index)
{
if (!desc_array_index) {
- vtn_assert(glsl_type_is_struct(var->type->type));
+ vtn_assert(glsl_type_is_struct_or_ifc(var->type->type));
desc_array_index = nir_imm_int(&b->nb, 0);
}
}
for (; idx < deref_chain->length; idx++) {
- if (glsl_type_is_struct(type->type)) {
+ if (glsl_type_is_struct_or_ifc(type->type)) {
vtn_assert(deref_chain->link[idx].mode == vtn_access_mode_literal);
unsigned field = deref_chain->link[idx].id;
tail = nir_build_deref_struct(&b->nb, tail, field);
break;
}
+ case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_STRUCT: {
vtn_assert(deref_chain->link[idx].mode == vtn_access_mode_literal);
unsigned member = deref_chain->link[idx].id;
static void
_vtn_local_load_store(struct vtn_builder *b, bool load, nir_deref_instr *deref,
- struct vtn_ssa_value *inout)
+ struct vtn_ssa_value *inout,
+ enum gl_access_qualifier access)
{
if (glsl_type_is_vector_or_scalar(deref->type)) {
if (load) {
- inout->def = nir_load_deref(&b->nb, deref);
+ inout->def = nir_load_deref_with_access(&b->nb, deref, access);
} else {
- nir_store_deref(&b->nb, deref, inout->def, ~0);
+ nir_store_deref_with_access(&b->nb, deref, inout->def, ~0, access);
}
} else if (glsl_type_is_array(deref->type) ||
glsl_type_is_matrix(deref->type)) {
unsigned elems = glsl_get_length(deref->type);
for (unsigned i = 0; i < elems; i++) {
nir_deref_instr *child =
- nir_build_deref_array(&b->nb, deref, nir_imm_int(&b->nb, i));
- _vtn_local_load_store(b, load, child, inout->elems[i]);
+ nir_build_deref_array_imm(&b->nb, deref, i);
+ _vtn_local_load_store(b, load, child, inout->elems[i], access);
}
} else {
- vtn_assert(glsl_type_is_struct(deref->type));
+ vtn_assert(glsl_type_is_struct_or_ifc(deref->type));
unsigned elems = glsl_get_length(deref->type);
for (unsigned i = 0; i < elems; i++) {
nir_deref_instr *child = nir_build_deref_struct(&b->nb, deref, i);
- _vtn_local_load_store(b, load, child, inout->elems[i]);
+ _vtn_local_load_store(b, load, child, inout->elems[i], access);
}
}
}
}
struct vtn_ssa_value *
-vtn_local_load(struct vtn_builder *b, nir_deref_instr *src)
+vtn_local_load(struct vtn_builder *b, nir_deref_instr *src,
+ enum gl_access_qualifier access)
{
nir_deref_instr *src_tail = get_deref_tail(src);
struct vtn_ssa_value *val = vtn_create_ssa_value(b, src_tail->type);
- _vtn_local_load_store(b, true, src_tail, val);
+ _vtn_local_load_store(b, true, src_tail, val, access);
if (src_tail != src) {
val->type = src->type;
void
vtn_local_store(struct vtn_builder *b, struct vtn_ssa_value *src,
- nir_deref_instr *dest)
+ nir_deref_instr *dest, enum gl_access_qualifier access)
{
nir_deref_instr *dest_tail = get_deref_tail(dest);
if (dest_tail != dest) {
struct vtn_ssa_value *val = vtn_create_ssa_value(b, dest_tail->type);
- _vtn_local_load_store(b, true, dest_tail, val);
+ _vtn_local_load_store(b, true, dest_tail, val, access);
if (nir_src_is_const(dest->arr.index))
val->def = vtn_vector_insert(b, val->def, src->def,
else
val->def = vtn_vector_insert_dynamic(b, val->def, src->def,
dest->arr.index.ssa);
- _vtn_local_load_store(b, false, dest_tail, val);
+ _vtn_local_load_store(b, false, dest_tail, val, access);
} else {
- _vtn_local_load_store(b, false, dest_tail, src);
+ _vtn_local_load_store(b, false, dest_tail, src, access);
}
}
nir_intrinsic_set_range(instr, access_size);
}
- if (op == nir_intrinsic_load_ssbo ||
+ if (op == nir_intrinsic_load_ubo ||
+ op == nir_intrinsic_load_ssbo ||
op == nir_intrinsic_store_ssbo) {
nir_intrinsic_set_access(instr, access);
}
return;
}
+ case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_STRUCT: {
unsigned elems = glsl_get_length(type->type);
for (unsigned i = 0; i < elems; i++) {
static void
_vtn_variable_load_store(struct vtn_builder *b, bool load,
struct vtn_pointer *ptr,
+ enum gl_access_qualifier access,
struct vtn_ssa_value **inout)
{
enum glsl_base_type base_type = glsl_get_base_type(ptr->type->type);
*/
if (load) {
*inout = vtn_create_ssa_value(b, ptr->type->type);
- (*inout)->def = nir_load_deref(&b->nb, deref);
+ (*inout)->def = nir_load_deref_with_access(&b->nb, deref,
+ ptr->type->access | access);
} else {
- nir_store_deref(&b->nb, deref, (*inout)->def, ~0);
+ nir_store_deref_with_access(&b->nb, deref, (*inout)->def, ~0,
+ ptr->type->access | access);
}
} else {
if (load) {
- *inout = vtn_local_load(b, deref);
+ *inout = vtn_local_load(b, deref, ptr->type->access | access);
} else {
- vtn_local_store(b, *inout, deref);
+ vtn_local_store(b, *inout, deref, ptr->type->access | access);
}
}
return;
}
/* Fall through */
+ case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_ARRAY:
case GLSL_TYPE_STRUCT: {
unsigned elems = glsl_get_length(ptr->type->type);
for (unsigned i = 0; i < elems; i++) {
chain.link[0].id = i;
struct vtn_pointer *elem = vtn_pointer_dereference(b, ptr, &chain);
- _vtn_variable_load_store(b, load, elem, &(*inout)->elems[i]);
+ _vtn_variable_load_store(b, load, elem, ptr->type->access | access,
+ &(*inout)->elems[i]);
}
return;
}
return vtn_block_load(b, src);
} else {
struct vtn_ssa_value *val = NULL;
- _vtn_variable_load_store(b, true, src, &val);
+ _vtn_variable_load_store(b, true, src, src->access, &val);
return val;
}
}
dest->mode == vtn_variable_mode_workgroup);
vtn_block_store(b, src, dest);
} else {
- _vtn_variable_load_store(b, false, dest, &src);
+ _vtn_variable_load_store(b, false, dest, dest->access, &src);
}
}
vtn_variable_store(b, vtn_variable_load(b, src), dest);
return;
+ case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_ARRAY:
case GLSL_TYPE_STRUCT: {
struct vtn_access_chain chain = {
*location = SYSTEM_VALUE_GLOBAL_INVOCATION_ID;
set_mode_system_value(b, mode);
break;
+ case SpvBuiltInGlobalLinearId:
+ *location = SYSTEM_VALUE_GLOBAL_INVOCATION_INDEX;
+ set_mode_system_value(b, mode);
+ break;
case SpvBuiltInBaseVertex:
/* OpenGL gl_BaseVertex (SYSTEM_VALUE_BASE_VERTEX) is not the same
* semantic as SPIR-V BaseVertex (SYSTEM_VALUE_FIRST_VERTEX).
set_mode_system_value(b, mode);
break;
default:
- vtn_fail("unsupported builtin: %u", builtin);
+ vtn_fail("Unsupported builtin: %s (%u)",
+ spirv_builtin_to_string(builtin), builtin);
}
}
break;
default:
- vtn_fail("Unhandled decoration");
+ vtn_fail_with_decoration("Unhandled decoration", dec->decoration);
}
}
}
}
+static void
+ptr_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
+ const struct vtn_decoration *dec, void *void_ptr)
+{
+ struct vtn_pointer *ptr = void_ptr;
+
+ switch (dec->decoration) {
+ case SpvDecorationNonUniformEXT:
+ ptr->access |= ACCESS_NON_UNIFORM;
+ break;
+
+ default:
+ break;
+ }
+}
+
static enum vtn_variable_mode
vtn_storage_class_to_mode(struct vtn_builder *b,
SpvStorageClass class,
break;
case SpvStorageClassGeneric:
default:
- vtn_fail("Unhandled variable storage class");
+ vtn_fail("Unhandled variable storage class: %s (%u)",
+ spirv_storageclass_to_string(class), class);
}
if (nir_mode_out)
} else {
const struct glsl_type *deref_type = ptr_type->deref->type;
if (!vtn_pointer_is_external_block(b, ptr)) {
- assert(ssa->bit_size == 32 && ssa->num_components == 1);
ptr->deref = nir_build_deref_cast(&b->nb, ssa, nir_mode,
- glsl_get_bare_type(deref_type), 0);
+ deref_type, 0);
} else if (vtn_type_contains_block(b, ptr->type) &&
ptr->mode != vtn_variable_mode_phys_ssbo) {
/* This is a pointer to somewhere in an array of blocks, not a
/* Private variables don't have any explicit layout but some layouts
* may have leaked through due to type deduplication in the SPIR-V.
*/
- var->var->type = glsl_get_bare_type(var->type->type);
+ var->var->type = var->type->type;
}
var->var->data.mode = nir_mode;
var->var->data.location = -1;
* layouts may have leaked through due to type deduplication in the
* SPIR-V.
*/
- var->var->type = glsl_get_bare_type(var->type->type);
+ var->var->type = var->type->type;
var->var->data.mode = nir_var_mem_shared;
}
break;
var->patch = false;
vtn_foreach_decoration(b, val, var_is_patch_cb, &var->patch);
if (glsl_type_is_array(var->type->type) &&
- glsl_type_is_struct(without_array->type)) {
+ glsl_type_is_struct_or_ifc(without_array->type)) {
vtn_foreach_decoration(b, vtn_value(b, without_array->id,
vtn_value_type_type),
var_is_patch_cb, &var->patch);
* the SPIR-V. We do, however, keep the layouts in the variable's
* interface_type because we need offsets for XFB arrays of blocks.
*/
- var->var->type = glsl_get_bare_type(var->type->type);
+ var->var->type = var->type->type;
var->var->data.mode = nir_mode;
var->var->data.patch = var->patch;
}
vtn_foreach_decoration(b, val, var_decoration_cb, var);
+ vtn_foreach_decoration(b, val, ptr_decoration_cb, val->pointer);
if ((var->mode == vtn_variable_mode_input ||
var->mode == vtn_variable_mode_output) &&
case SpvOpAccessChain:
case SpvOpPtrAccessChain:
- case SpvOpInBoundsAccessChain: {
+ case SpvOpInBoundsAccessChain:
+ case SpvOpInBoundsPtrAccessChain: {
struct vtn_access_chain *chain = vtn_access_chain_create(b, count - 4);
- chain->ptr_as_array = (opcode == SpvOpPtrAccessChain);
+ chain->ptr_as_array = (opcode == SpvOpPtrAccessChain || opcode == SpvOpInBoundsPtrAccessChain);
unsigned idx = 0;
for (int i = 4; i < count; i++) {
struct vtn_value *link_val = vtn_untyped_value(b, w[i]);
if (link_val->value_type == vtn_value_type_constant) {
chain->link[idx].mode = vtn_access_mode_literal;
- switch (glsl_get_bit_size(link_val->type->type)) {
+ const unsigned bit_size = glsl_get_bit_size(link_val->type->type);
+ switch (bit_size) {
case 8:
- chain->link[idx].id = link_val->constant->values[0].i8[0];
+ chain->link[idx].id = link_val->constant->values[0][0].i8;
break;
case 16:
- chain->link[idx].id = link_val->constant->values[0].i16[0];
+ chain->link[idx].id = link_val->constant->values[0][0].i16;
break;
case 32:
- chain->link[idx].id = link_val->constant->values[0].i32[0];
+ chain->link[idx].id = link_val->constant->values[0][0].i32;
break;
case 64:
- chain->link[idx].id = link_val->constant->values[0].i64[0];
+ chain->link[idx].id = link_val->constant->values[0][0].i64;
break;
default:
- vtn_fail("Invalid bit size");
+ vtn_fail("Invalid bit size: %u", bit_size);
}
} else {
chain->link[idx].mode = vtn_access_mode_id;
val->sampled_image->image =
vtn_pointer_dereference(b, base_val->sampled_image->image, chain);
val->sampled_image->sampler = base_val->sampled_image->sampler;
+ vtn_foreach_decoration(b, val, ptr_decoration_cb,
+ val->sampled_image->image);
+ vtn_foreach_decoration(b, val, ptr_decoration_cb,
+ val->sampled_image->sampler);
} else {
vtn_assert(base_val->value_type == vtn_value_type_pointer);
struct vtn_value *val =
vtn_push_value(b, w[2], vtn_value_type_pointer);
val->pointer = vtn_pointer_dereference(b, base_val->pointer, chain);
val->pointer->ptr_type = ptr_type;
+ vtn_foreach_decoration(b, val, ptr_decoration_cb, val->pointer);
}
break;
}
case SpvOpCopyMemorySized:
default:
- vtn_fail("Unhandled opcode");
+ vtn_fail_with_opcode("Unhandled opcode", opcode);
}
}