|
|
@@ -1101,10 +1101,18 @@ static void |
|
|
|
vtn_handle_type(struct vtn_builder *b, SpvOp opcode, |
|
|
|
const uint32_t *w, unsigned count) |
|
|
|
{ |
|
|
|
struct vtn_value *val = vtn_push_value(b, w[1], vtn_value_type_type); |
|
|
|
struct vtn_value *val = NULL; |
|
|
|
|
|
|
|
val->type = rzalloc(b, struct vtn_type); |
|
|
|
val->type->id = w[1]; |
|
|
|
/* In order to properly handle forward declarations, we have to defer |
|
|
|
* allocation for pointer types. |
|
|
|
*/ |
|
|
|
if (opcode != SpvOpTypePointer && opcode != SpvOpTypeForwardPointer) { |
|
|
|
val = vtn_push_value(b, w[1], vtn_value_type_type); |
|
|
|
vtn_fail_if(val->type != NULL, |
|
|
|
"Only pointers can have forward declarations"); |
|
|
|
val->type = rzalloc(b, struct vtn_type); |
|
|
|
val->type->id = w[1]; |
|
|
|
} |
|
|
|
|
|
|
|
switch (opcode) { |
|
|
|
case SpvOpTypeVoid: |
|
|
@@ -1274,46 +1282,70 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode, |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
case SpvOpTypePointer: { |
|
|
|
case SpvOpTypePointer: |
|
|
|
case SpvOpTypeForwardPointer: { |
|
|
|
/* We can't blindly push the value because it might be a forward |
|
|
|
* declaration. |
|
|
|
*/ |
|
|
|
val = vtn_untyped_value(b, w[1]); |
|
|
|
|
|
|
|
SpvStorageClass storage_class = w[2]; |
|
|
|
struct vtn_type *deref_type = |
|
|
|
vtn_value(b, w[3], vtn_value_type_type)->type; |
|
|
|
|
|
|
|
val->type->base_type = vtn_base_type_pointer; |
|
|
|
val->type->storage_class = storage_class; |
|
|
|
val->type->deref = deref_type; |
|
|
|
if (val->value_type == vtn_value_type_invalid) { |
|
|
|
val->value_type = vtn_value_type_type; |
|
|
|
val->type = rzalloc(b, struct vtn_type); |
|
|
|
val->type->id = w[1]; |
|
|
|
val->type->base_type = vtn_base_type_pointer; |
|
|
|
val->type->storage_class = storage_class; |
|
|
|
|
|
|
|
vtn_foreach_decoration(b, val, array_stride_decoration_cb, NULL); |
|
|
|
/* These can actually be stored to nir_variables and used as SSA |
|
|
|
* values so they need a real glsl_type. |
|
|
|
*/ |
|
|
|
switch (storage_class) { |
|
|
|
case SpvStorageClassUniform: |
|
|
|
val->type->type = b->options->ubo_ptr_type; |
|
|
|
break; |
|
|
|
case SpvStorageClassStorageBuffer: |
|
|
|
val->type->type = b->options->ssbo_ptr_type; |
|
|
|
break; |
|
|
|
case SpvStorageClassPushConstant: |
|
|
|
val->type->type = b->options->push_const_ptr_type; |
|
|
|
break; |
|
|
|
case SpvStorageClassWorkgroup: |
|
|
|
val->type->type = b->options->shared_ptr_type; |
|
|
|
break; |
|
|
|
default: |
|
|
|
/* In this case, no variable pointers are allowed so all deref |
|
|
|
* chains are complete back to the variable and it doesn't matter |
|
|
|
* what type gets used so we leave it NULL. |
|
|
|
*/ |
|
|
|
break; |
|
|
|
} |
|
|
|
} else { |
|
|
|
vtn_fail_if(val->type->storage_class != storage_class, |
|
|
|
"The storage classes of an OpTypePointer and any " |
|
|
|
"OpTypeForwardPointers that provide forward " |
|
|
|
"declarations of it must match."); |
|
|
|
} |
|
|
|
|
|
|
|
/* These can actually be stored to nir_variables and used as SSA |
|
|
|
* values so they need a real glsl_type. |
|
|
|
*/ |
|
|
|
switch (storage_class) { |
|
|
|
case SpvStorageClassUniform: |
|
|
|
val->type->type = b->options->ubo_ptr_type; |
|
|
|
break; |
|
|
|
case SpvStorageClassStorageBuffer: |
|
|
|
val->type->type = b->options->ssbo_ptr_type; |
|
|
|
break; |
|
|
|
case SpvStorageClassPushConstant: |
|
|
|
val->type->type = b->options->push_const_ptr_type; |
|
|
|
break; |
|
|
|
case SpvStorageClassWorkgroup: |
|
|
|
val->type->type = b->options->shared_ptr_type; |
|
|
|
if (b->options->lower_workgroup_access_to_offsets) { |
|
|
|
if (opcode == SpvOpTypePointer) { |
|
|
|
vtn_fail_if(val->type->deref != NULL, |
|
|
|
"While OpTypeForwardPointer can be used to provide a " |
|
|
|
"forward declaration of a pointer, OpTypePointer can " |
|
|
|
"only be used once for a given id."); |
|
|
|
|
|
|
|
val->type->deref = vtn_value(b, w[3], vtn_value_type_type)->type; |
|
|
|
|
|
|
|
vtn_foreach_decoration(b, val, array_stride_decoration_cb, NULL); |
|
|
|
|
|
|
|
if (storage_class == SpvStorageClassWorkgroup && |
|
|
|
b->options->lower_workgroup_access_to_offsets) { |
|
|
|
uint32_t size, align; |
|
|
|
val->type->deref = vtn_type_layout_std430(b, val->type->deref, |
|
|
|
&size, &align); |
|
|
|
val->type->length = size; |
|
|
|
val->type->align = align; |
|
|
|
} |
|
|
|
break; |
|
|
|
default: |
|
|
|
/* In this case, no variable pointers are allowed so all deref chains |
|
|
|
* are complete back to the variable and it doesn't matter what type |
|
|
|
* gets used so we leave it NULL. |
|
|
|
*/ |
|
|
|
break; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
@@ -3931,6 +3963,7 @@ vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode, |
|
|
|
case SpvOpTypeStruct: |
|
|
|
case SpvOpTypeOpaque: |
|
|
|
case SpvOpTypePointer: |
|
|
|
case SpvOpTypeForwardPointer: |
|
|
|
case SpvOpTypeFunction: |
|
|
|
case SpvOpTypeEvent: |
|
|
|
case SpvOpTypeDeviceEvent: |