vtn_decorate_pointer(struct vtn_builder *b, struct vtn_value *val,
struct vtn_pointer *ptr)
{
- struct vtn_pointer dummy = { };
+ struct vtn_pointer dummy = { .access = 0 };
vtn_foreach_decoration(b, val, ptr_decoration_cb, &dummy);
/* If we're adding access flags, make a copy of the pointer. We could
static void
ssa_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
- const struct vtn_decoration *dec, void *void_ssa)
+ const struct vtn_decoration *dec, void *void_ctx)
{
- struct vtn_ssa_value *ssa = void_ssa;
-
switch (dec->decoration) {
case SpvDecorationNonUniformEXT:
- ssa->access |= ACCESS_NON_UNIFORM;
+ if (val->value_type == vtn_value_type_ssa) {
+ val->ssa->access |= ACCESS_NON_UNIFORM;
+ } else if (val->value_type == vtn_value_type_pointer) {
+ val->pointer->access |= ACCESS_NON_UNIFORM;
+ } else if (val->value_type == vtn_value_type_sampled_image) {
+ val->sampled_image->image->access |= ACCESS_NON_UNIFORM;
+ } else if (val->value_type == vtn_value_type_image_pointer) {
+ val->image->image->access |= ACCESS_NON_UNIFORM;
+ }
break;
default:
} else {
val = vtn_push_value(b, value_id, vtn_value_type_ssa);
val->ssa = ssa;
- vtn_foreach_decoration(b, val, ssa_decoration_cb, val->ssa);
+ vtn_foreach_decoration(b, val, ssa_decoration_cb, NULL);
}
return val;
}
+void
+vtn_copy_value(struct vtn_builder *b, uint32_t src_value_id,
+ uint32_t dst_value_id)
+{
+ struct vtn_value *src = vtn_untyped_value(b, src_value_id);
+ struct vtn_value *dst = vtn_push_value(b, dst_value_id, src->value_type);
+ struct vtn_value src_copy = *src;
+
+ vtn_fail_if(dst->type->id != src->type->id,
+ "Result Type must equal Operand type");
+
+ src_copy.name = dst->name;
+ src_copy.decoration = dst->decoration;
+ src_copy.type = dst->type;
+ *dst = src_copy;
+
+ vtn_foreach_decoration(b, dst, ssa_decoration_cb, NULL);
+}
+
static struct vtn_access_chain *
vtn_access_chain_create(struct vtn_builder *b, unsigned length)
{
}
}
-struct vtn_pointer *
-vtn_pointer_for_variable(struct vtn_builder *b,
- struct vtn_variable *var, struct vtn_type *ptr_type)
-{
- struct vtn_pointer *pointer = rzalloc(b, struct vtn_pointer);
-
- pointer->mode = var->mode;
- pointer->type = var->type;
- vtn_assert(ptr_type->base_type == vtn_base_type_pointer);
- 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;
-}
-
/* Returns an atomic_uint type based on the original uint type. The returned
* type will be equivalent to the original one but will have an atomic_uint
* type as leaf instead of an uint.
if (src_tail != src) {
val->type = src->type;
- if (nir_src_is_const(src->arr.index))
- val->def = vtn_vector_extract(b, val->def,
- nir_src_as_uint(src->arr.index));
- else
- val->def = vtn_vector_extract_dynamic(b, val->def, src->arr.index.ssa);
+ val->def = nir_vector_extract(&b->nb, val->def, src->arr.index.ssa);
}
return val;
struct vtn_ssa_value *val = vtn_create_ssa_value(b, dest_tail->type);
_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,
- nir_src_as_uint(dest->arr.index));
- else
- val->def = vtn_vector_insert_dynamic(b, val->def, src->def,
- dest->arr.index.ssa);
+ val->def = nir_vector_insert(&b->nb, val->def, src->def,
+ dest->arr.index.ssa);
_vtn_local_load_store(b, false, dest_tail, val, access);
} else {
_vtn_local_load_store(b, false, dest_tail, src, access);
*location = SYSTEM_VALUE_GLOBAL_GROUP_SIZE;
set_mode_system_value(b, mode);
break;
+ case SpvBuiltInBaryCoordNoPerspAMD:
+ *location = SYSTEM_VALUE_BARYCENTRIC_LINEAR_PIXEL;
+ set_mode_system_value(b, mode);
+ break;
+ case SpvBuiltInBaryCoordNoPerspCentroidAMD:
+ *location = SYSTEM_VALUE_BARYCENTRIC_LINEAR_CENTROID;
+ set_mode_system_value(b, mode);
+ break;
+ case SpvBuiltInBaryCoordNoPerspSampleAMD:
+ *location = SYSTEM_VALUE_BARYCENTRIC_LINEAR_SAMPLE;
+ set_mode_system_value(b, mode);
+ break;
+ case SpvBuiltInBaryCoordSmoothAMD:
+ *location = SYSTEM_VALUE_BARYCENTRIC_PERSP_PIXEL;
+ set_mode_system_value(b, mode);
+ break;
+ case SpvBuiltInBaryCoordSmoothCentroidAMD:
+ *location = SYSTEM_VALUE_BARYCENTRIC_PERSP_CENTROID;
+ set_mode_system_value(b, mode);
+ break;
+ case SpvBuiltInBaryCoordSmoothSampleAMD:
+ *location = SYSTEM_VALUE_BARYCENTRIC_PERSP_SAMPLE;
+ set_mode_system_value(b, mode);
+ break;
+ case SpvBuiltInBaryCoordPullModelAMD:
+ *location = SYSTEM_VALUE_BARYCENTRIC_PULL_MODEL;
+ set_mode_system_value(b, mode);
+ break;
default:
vtn_fail("Unsupported builtin: %s (%u)",
spirv_builtin_to_string(builtin), builtin);
case SpvDecorationFlat:
var_data->interpolation = INTERP_MODE_FLAT;
break;
+ case SpvDecorationExplicitInterpAMD:
+ var_data->interpolation = INTERP_MODE_EXPLICIT;
+ break;
case SpvDecorationCentroid:
var_data->centroid = true;
break;
var_data->read_only = true;
break;
case SpvDecorationNonReadable:
- var_data->image.access |= ACCESS_NON_READABLE;
+ var_data->access |= ACCESS_NON_READABLE;
break;
case SpvDecorationNonWritable:
var_data->read_only = true;
- var_data->image.access |= ACCESS_NON_WRITEABLE;
+ var_data->access |= ACCESS_NON_WRITEABLE;
break;
case SpvDecorationRestrict:
- var_data->image.access |= ACCESS_RESTRICT;
+ var_data->access |= ACCESS_RESTRICT;
break;
case SpvDecorationVolatile:
- var_data->image.access |= ACCESS_VOLATILE;
+ var_data->access |= ACCESS_VOLATILE;
break;
case SpvDecorationCoherent:
- var_data->image.access |= ACCESS_COHERENT;
+ var_data->access |= ACCESS_COHERENT;
break;
case SpvDecorationComponent:
var_data->location_frac = dec->operands[0];
mode = vtn_variable_mode_ssbo;
nir_mode = nir_var_mem_ssbo;
break;
- case SpvStorageClassPhysicalStorageBufferEXT:
+ case SpvStorageClassPhysicalStorageBuffer:
mode = vtn_variable_mode_phys_ssbo;
nir_mode = nir_var_mem_global;
break;
case SpvStorageClassUniformConstant:
- mode = vtn_variable_mode_uniform;
- nir_mode = nir_var_uniform;
+ if (b->shader->info.stage == MESA_SHADER_KERNEL) {
+ if (b->options->constant_as_global) {
+ mode = vtn_variable_mode_cross_workgroup;
+ nir_mode = nir_var_mem_global;
+ } else {
+ mode = vtn_variable_mode_ubo;
+ nir_mode = nir_var_mem_ubo;
+ }
+ } else {
+ mode = vtn_variable_mode_uniform;
+ nir_mode = nir_var_uniform;
+ }
break;
case SpvStorageClassPushConstant:
mode = vtn_variable_mode_push_constant;
/* In this case, we're looking for a block index and not an actual
* deref.
*
- * For PhysicalStorageBufferEXT pointers, we don't have a block index
+ * For PhysicalStorageBuffer pointers, we don't have a block index
* at all because we get the pointer directly from the client. This
* assumes that there will never be a SSBO binding variable using the
- * PhysicalStorageBufferEXT storage class. This assumption appears
+ * PhysicalStorageBuffer storage class. This assumption appears
* to be correct according to the Vulkan spec because the table,
* "Shader Resource and Storage Class Correspondence," the only the
* Uniform storage class with BufferBlock or the StorageBuffer
/* This is a pointer to something internal or a pointer inside a
* block. It's just a regular cast.
*
- * For PhysicalStorageBufferEXT pointers, we don't have a block index
+ * For PhysicalStorageBuffer pointers, we don't have a block index
* at all because we get the pointer directly from the client. This
* assumes that there will never be a SSBO binding variable using the
- * PhysicalStorageBufferEXT storage class. This assumption appears
+ * PhysicalStorageBuffer storage class. This assumption appears
* to be correct according to the Vulkan spec because the table,
* "Shader Resource and Storage Class Correspondence," the only the
* Uniform storage class with BufferBlock or the StorageBuffer
static void
vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
struct vtn_type *ptr_type, SpvStorageClass storage_class,
- nir_constant *initializer)
+ nir_constant *const_initializer, nir_variable *var_initializer)
{
vtn_assert(ptr_type->base_type == vtn_base_type_pointer);
struct vtn_type *type = ptr_type->deref;
case vtn_variable_mode_phys_ssbo:
vtn_fail("Cannot create a variable with the "
- "PhysicalStorageBufferEXT storage class");
+ "PhysicalStorageBuffer storage class");
break;
default:
var->mode = mode;
var->base_location = -1;
- vtn_assert(val->value_type == vtn_value_type_pointer);
- val->pointer = vtn_pointer_for_variable(b, var, ptr_type);
+ val->pointer = rzalloc(b, struct vtn_pointer);
+ val->pointer->mode = var->mode;
+ val->pointer->type = var->type;
+ val->pointer->ptr_type = ptr_type;
+ val->pointer->var = var;
+ val->pointer->access = var->type->access;
switch (var->mode) {
case vtn_variable_mode_function:
unreachable("Should have been caught before");
}
- if (initializer) {
+ /* We can only have one type of initializer */
+ assert(!(const_initializer && var_initializer));
+ if (const_initializer) {
var->var->constant_initializer =
- nir_constant_clone(initializer, var->var);
+ nir_constant_clone(const_initializer, var->var);
}
+ if (var_initializer)
+ var->var->pointer_initializer = var_initializer;
vtn_foreach_decoration(b, val, var_decoration_cb, var);
vtn_foreach_decoration(b, val, ptr_decoration_cb, val->pointer);
+ /* Propagate access flags from the OpVariable decorations. */
+ val->pointer->access |= var->access;
+
if ((var->mode == vtn_variable_mode_input ||
var->mode == vtn_variable_mode_output) &&
var->var->members) {
struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer);
SpvStorageClass storage_class = w[3];
- nir_constant *initializer = NULL;
- if (count > 4)
- initializer = vtn_value(b, w[4], vtn_value_type_constant)->constant;
+ nir_constant *const_initializer = NULL;
+ nir_variable *var_initializer = NULL;
+ if (count > 4) {
+ struct vtn_value *init = vtn_untyped_value(b, w[4]);
+ switch (init->value_type) {
+ case vtn_value_type_constant:
+ const_initializer = init->constant;
+ break;
+ case vtn_value_type_pointer:
+ var_initializer = init->pointer->var->var;
+ break;
+ default:
+ vtn_fail("SPIR-V variable initializer %u must be constant or pointer",
+ w[4]);
+ }
+ }
+
+ vtn_create_variable(b, val, ptr_type, storage_class, const_initializer, var_initializer);
- vtn_create_variable(b, val, ptr_type, storage_class, initializer);
break;
}
vtn_warn("OpStore of a sampler detected. Doing on-the-fly copy "
"propagation to workaround the problem.");
vtn_assert(dest->var->copy_prop_sampler == NULL);
- dest->var->copy_prop_sampler =
- vtn_value(b, w[2], vtn_value_type_pointer)->pointer;
+ struct vtn_value *v = vtn_untyped_value(b, w[2]);
+ if (v->value_type == vtn_value_type_sampled_image) {
+ dest->var->copy_prop_sampler = v->sampled_image->sampler;
+ } else {
+ vtn_assert(v->value_type == vtn_value_type_pointer);
+ dest->var->copy_prop_sampler = v->pointer;
+ }
} else {
vtn_fail("Vulkan does not allow OpStore of a sampler or image.");
}
case SpvOpConvertUToPtr: {
struct vtn_value *ptr_val =
vtn_push_value(b, w[2], vtn_value_type_pointer);
- struct vtn_value *u_val = vtn_value(b, w[3], vtn_value_type_ssa);
+ struct vtn_value *u_val = vtn_untyped_value(b, w[3]);
vtn_fail_if(ptr_val->type->type == NULL,
"OpConvertUToPtr can only be used on physical pointers");
"OpConvertUToPtr can only be used to cast from a vector or "
"scalar type");
- nir_ssa_def *ptr_ssa = nir_sloppy_bitcast(&b->nb, u_val->ssa->def,
+ struct vtn_ssa_value *u_ssa = vtn_ssa_value(b, w[3]);
+ nir_ssa_def *ptr_ssa = nir_sloppy_bitcast(&b->nb, u_ssa->def,
ptr_val->type->type);
ptr_val->pointer = vtn_pointer_from_ssa(b, ptr_ssa, ptr_val->type);
vtn_foreach_decoration(b, ptr_val, ptr_decoration_cb, ptr_val->pointer);