#include "nir_deref.h"
#include <vulkan/vulkan_core.h>
+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_value *
+vtn_push_value_pointer(struct vtn_builder *b, uint32_t value_id,
+ struct vtn_pointer *ptr)
+{
+ struct vtn_value *val = vtn_push_value(b, value_id, vtn_value_type_pointer);
+ val->pointer = ptr;
+ vtn_foreach_decoration(b, val, ptr_decoration_cb, ptr);
+ return val;
+}
+
+static void
+ssa_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
+ const struct vtn_decoration *dec, void *void_ssa)
+{
+ struct vtn_ssa_value *ssa = void_ssa;
+
+ switch (dec->decoration) {
+ case SpvDecorationNonUniformEXT:
+ ssa->access |= ACCESS_NON_UNIFORM;
+ break;
+
+ default:
+ break;
+ }
+}
+
+struct vtn_value *
+vtn_push_ssa(struct vtn_builder *b, uint32_t value_id,
+ struct vtn_type *type, struct vtn_ssa_value *ssa)
+{
+ struct vtn_value *val;
+ if (type->base_type == vtn_base_type_pointer) {
+ val = vtn_push_value_pointer(b, value_id, vtn_pointer_from_ssa(b, ssa->def, type));
+ } 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);
+ }
+ return val;
+}
+
static struct vtn_access_chain *
vtn_access_chain_create(struct vtn_builder *b, unsigned length)
{
return ((mode == vtn_variable_mode_ubo ||
mode == vtn_variable_mode_ssbo) &&
b->options->lower_ubo_ssbo_access_to_offsets) ||
- mode == vtn_variable_mode_push_constant ||
- (mode == vtn_variable_mode_workgroup &&
- b->options->lower_workgroup_access_to_offsets);
+ mode == vtn_variable_mode_push_constant;
}
static bool
return ptr->mode == vtn_variable_mode_ssbo ||
ptr->mode == vtn_variable_mode_ubo ||
ptr->mode == vtn_variable_mode_phys_ssbo ||
- ptr->mode == vtn_variable_mode_push_constant ||
- (ptr->mode == vtn_variable_mode_workgroup &&
- b->options->lower_workgroup_access_to_offsets);
+ ptr->mode == vtn_variable_mode_push_constant;
}
static nir_ssa_def *
vtn_variable_resource_index(struct vtn_builder *b, struct vtn_variable *var,
nir_ssa_def *desc_array_index)
{
+ vtn_assert(b->options->environment == NIR_SPIRV_VULKAN);
+
if (!desc_array_index) {
vtn_assert(glsl_type_is_struct_or_ifc(var->type->type));
desc_array_index = nir_imm_int(&b->nb, 0);
vtn_resource_reindex(struct vtn_builder *b, enum vtn_variable_mode mode,
nir_ssa_def *base_index, nir_ssa_def *offset_index)
{
+ vtn_assert(b->options->environment == NIR_SPIRV_VULKAN);
+
nir_intrinsic_instr *instr =
nir_intrinsic_instr_create(b->nb.shader,
nir_intrinsic_vulkan_resource_reindex);
vtn_descriptor_load(struct vtn_builder *b, enum vtn_variable_mode mode,
nir_ssa_def *desc_index)
{
+ vtn_assert(b->options->environment == NIR_SPIRV_VULKAN);
+
nir_intrinsic_instr *desc_load =
nir_intrinsic_instr_create(b->nb.shader,
nir_intrinsic_load_vulkan_descriptor);
struct vtn_access_chain *deref_chain)
{
struct vtn_type *type = base->type;
- enum gl_access_qualifier access = base->access;
+ enum gl_access_qualifier access = base->access | deref_chain->access;
unsigned idx = 0;
nir_deref_instr *tail;
if (base->deref) {
tail = base->deref;
- } else if (vtn_pointer_is_external_block(b, base)) {
+ } else if (b->options->environment == NIR_SPIRV_VULKAN &&
+ vtn_pointer_is_external_block(b, base)) {
nir_ssa_def *block_index = base->block_index;
/* We dereferencing an external block pointer. Correctness of this
set_mode_system_value(b, mode);
break;
case SpvBuiltInFragCoord:
- *location = VARYING_SLOT_POS;
vtn_assert(*mode == nir_var_shader_in);
+ if (b->options && b->options->frag_coord_is_sysval) {
+ *mode = nir_var_system_value;
+ *location = SYSTEM_VALUE_FRAG_COORD;
+ } else {
+ *location = VARYING_SLOT_POS;
+ }
break;
case SpvBuiltInPointCoord:
*location = VARYING_SLOT_PNTC;
break;
case SpvBuiltInBaseVertex:
/* OpenGL gl_BaseVertex (SYSTEM_VALUE_BASE_VERTEX) is not the same
- * semantic as SPIR-V BaseVertex (SYSTEM_VALUE_FIRST_VERTEX).
+ * semantic as Vulkan BaseVertex (SYSTEM_VALUE_FIRST_VERTEX).
*/
- *location = SYSTEM_VALUE_FIRST_VERTEX;
+ if (b->options->environment == NIR_SPIRV_OPENGL)
+ *location = SYSTEM_VALUE_BASE_VERTEX;
+ else
+ *location = SYSTEM_VALUE_FIRST_VERTEX;
set_mode_system_value(b, mode);
break;
case SpvBuiltInBaseInstance:
case SpvDecorationXfbBuffer:
var_data->explicit_xfb_buffer = true;
- var_data->xfb_buffer = dec->operands[0];
+ var_data->xfb.buffer = dec->operands[0];
var_data->always_active_io = true;
break;
case SpvDecorationXfbStride:
var_data->explicit_xfb_stride = true;
- var_data->xfb_stride = dec->operands[0];
+ var_data->xfb.stride = dec->operands[0];
break;
case SpvDecorationOffset:
var_data->explicit_offset = true;
break;
case SpvDecorationCounterBuffer:
/* Counter buffer decorations can safely be ignored by the driver. */
- break;
+ return;
default:
break;
}
*/
vtn_assert(vtn_var->mode == vtn_variable_mode_ubo ||
vtn_var->mode == vtn_variable_mode_ssbo ||
- vtn_var->mode == vtn_variable_mode_push_constant ||
- (vtn_var->mode == vtn_variable_mode_workgroup &&
- b->options->lower_workgroup_access_to_offsets));
+ vtn_var->mode == vtn_variable_mode_push_constant);
}
}
}
var->var->interface_type = NULL;
break;
+ case vtn_variable_mode_ubo:
+ case vtn_variable_mode_ssbo:
+ var->var = rzalloc(b->shader, nir_variable);
+ var->var->name = ralloc_strdup(var->var, val->name);
+
+ var->var->type = var->type->type;
+ var->var->interface_type = var->type->type;
+
+ var->var->data.mode = nir_mode;
+ var->var->data.location = -1;
+
+ break;
+
case vtn_variable_mode_workgroup:
- if (b->options->lower_workgroup_access_to_offsets) {
- var->shared_location = -1;
- } else {
- /* Create the variable normally */
- var->var = rzalloc(b->shader, nir_variable);
- var->var->name = ralloc_strdup(var->var, val->name);
- /* Workgroup 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 = var->type->type;
- var->var->data.mode = nir_var_mem_shared;
- }
+ /* Create the variable normally */
+ var->var = rzalloc(b->shader, nir_variable);
+ var->var->name = ralloc_strdup(var->var, val->name);
+ /* Workgroup 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 = var->type->type;
+ var->var->data.mode = nir_var_mem_shared;
break;
case vtn_variable_mode_input:
break;
}
- case vtn_variable_mode_ubo:
- case vtn_variable_mode_ssbo:
case vtn_variable_mode_push_constant:
case vtn_variable_mode_cross_workgroup:
/* These don't need actual variables. */
assign_missing_member_locations(var);
}
- if (var->mode == vtn_variable_mode_uniform) {
+ if (var->mode == vtn_variable_mode_uniform ||
+ var->mode == vtn_variable_mode_ubo ||
+ var->mode == vtn_variable_mode_ssbo) {
/* XXX: We still need the binding information in the nir_variable
* for these. We should fix that.
*/
case SpvOpInBoundsAccessChain:
case SpvOpInBoundsPtrAccessChain: {
struct vtn_access_chain *chain = vtn_access_chain_create(b, count - 4);
+ enum gl_access_qualifier access = 0;
chain->ptr_as_array = (opcode == SpvOpPtrAccessChain || opcode == SpvOpInBoundsPtrAccessChain);
unsigned idx = 0;
} else {
chain->link[idx].mode = vtn_access_mode_id;
chain->link[idx].id = w[i];
-
}
+ access |= vtn_value_access(link_val);
idx++;
}
struct vtn_value *val =
vtn_push_value(b, w[2], vtn_value_type_sampled_image);
val->sampled_image = ralloc(b, struct vtn_sampled_image);
- val->sampled_image->type = base_val->sampled_image->type;
val->sampled_image->image =
vtn_pointer_dereference(b, base_val->sampled_image->image, chain);
val->sampled_image->sampler = base_val->sampled_image->sampler;
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);
+ struct vtn_pointer *ptr =
+ vtn_pointer_dereference(b, base_val->pointer, chain);
+ ptr->ptr_type = ptr_type;
+ ptr->access |= access;
+ vtn_push_value_pointer(b, w[2], ptr);
}
break;
}
if (glsl_type_is_image(res_type->type) ||
glsl_type_is_sampler(res_type->type)) {
- vtn_push_value(b, w[2], vtn_value_type_pointer)->pointer = src;
+ vtn_push_value_pointer(b, w[2], src);
return;
}
+ if (count > 4) {
+ unsigned idx = 5;
+ SpvMemoryAccessMask access = w[4];
+ if (access & SpvMemoryAccessAlignedMask)
+ idx++;
+
+ if (access & SpvMemoryAccessMakePointerVisibleMask) {
+ SpvMemorySemanticsMask semantics =
+ SpvMemorySemanticsMakeVisibleMask |
+ vtn_storage_class_to_memory_semantics(src->ptr_type->storage_class);
+
+ SpvScope scope = vtn_constant_uint(b, w[idx]);
+ vtn_emit_memory_barrier(b, scope, semantics);
+ }
+ }
+
vtn_push_ssa(b, w[2], res_type, vtn_variable_load(b, src));
break;
}
struct vtn_ssa_value *src = vtn_ssa_value(b, w[2]);
vtn_variable_store(b, src, dest);
+
+ if (count > 3) {
+ unsigned idx = 4;
+ SpvMemoryAccessMask access = w[3];
+
+ if (access & SpvMemoryAccessAlignedMask)
+ idx++;
+
+ if (access & SpvMemoryAccessMakePointerAvailableMask) {
+ SpvMemorySemanticsMask semantics =
+ SpvMemorySemanticsMakeAvailableMask |
+ vtn_storage_class_to_memory_semantics(dest->ptr_type->storage_class);
+ SpvScope scope = vtn_constant_uint(b, w[idx]);
+ vtn_emit_memory_barrier(b, scope, semantics);
+ }
+ }
break;
}
"scalar type");
/* The pointer will be converted to an SSA value automatically */
- nir_ssa_def *ptr_ssa = vtn_ssa_value(b, w[3])->def;
+ struct vtn_ssa_value *ptr_ssa = vtn_ssa_value(b, w[3]);
u_val->ssa = vtn_create_ssa_value(b, u_val->type->type);
- u_val->ssa->def = nir_sloppy_bitcast(&b->nb, ptr_ssa, u_val->type->type);
+ u_val->ssa->def = nir_sloppy_bitcast(&b->nb, ptr_ssa->def, u_val->type->type);
+ u_val->ssa->access |= ptr_ssa->access;
break;
}
nir_ssa_def *ptr_ssa = nir_sloppy_bitcast(&b->nb, u_val->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);
+ ptr_val->pointer->access |= u_val->ssa->access;
break;
}