summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2018-03-22 08:50:34 -0700
committerJason Ekstrand <[email protected]>2018-06-22 20:15:57 -0700
commit7dfa440922f562ae41d0671219ace8ef2217804a (patch)
tree09fdb7d098e0732a4f0c472348e153989f9776f6 /src/compiler
parentb0c643d8f579a3e1e45a08f6d9de099f2c45898b (diff)
spirv: Make push constants an offset-based pointer
Push constants have been a weird edge-case for a while in that they have explitic offsets but we've been internally building access chains for them. This mostly works but it means that passing pointers to push constants through as function arguments is broken. The easy thing to do for now is to just treat them like UBOs or SSBOs only without a block index. This does loose a bit of information since we no longer have an accurate access range and any indirect access will look like it could read the whole block. Unfortunately, there's not much we can do about that. Once NIR derefs get a bit more powerful, we can plumb these through as derefs and be able to reason about them again. Acked-by: Rob Clark <[email protected]> Acked-by: Bas Nieuwenhuizen <[email protected]> Acked-by: Dave Airlie <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/spirv/spirv_to_nir.c7
-rw-r--r--src/compiler/spirv/vtn_variables.c38
2 files changed, 17 insertions, 28 deletions
diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c
index ab624866fb4..fb62f3035a9 100644
--- a/src/compiler/spirv/spirv_to_nir.c
+++ b/src/compiler/spirv/spirv_to_nir.c
@@ -1182,6 +1182,13 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
val->type->type = glsl_vector_type(GLSL_TYPE_UINT, 2);
}
+ if (storage_class == SpvStorageClassPushConstant) {
+ /* These can actually be stored to nir_variables and used as SSA
+ * values so they need a real glsl_type.
+ */
+ val->type->type = glsl_uint_type();
+ }
+
if (storage_class == SpvStorageClassWorkgroup &&
b->options->lower_workgroup_access_to_offsets) {
uint32_t size, align;
diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c
index 09d61803d1b..ee2bbfe799a 100644
--- a/src/compiler/spirv/vtn_variables.c
+++ b/src/compiler/spirv/vtn_variables.c
@@ -64,6 +64,7 @@ vtn_pointer_uses_ssa_offset(struct vtn_builder *b,
{
return ptr->mode == vtn_variable_mode_ubo ||
ptr->mode == vtn_variable_mode_ssbo ||
+ ptr->mode == vtn_variable_mode_push_constant ||
(ptr->mode == vtn_variable_mode_workgroup &&
b->options->lower_workgroup_access_to_offsets);
}
@@ -269,6 +270,12 @@ vtn_ssa_offset_pointer_dereference(struct vtn_builder *b,
}
offset = nir_imm_int(&b->nb, base->var->shared_location);
+ } else if (base->mode == vtn_variable_mode_push_constant) {
+ /* Push constants neither need nor have a block index */
+ vtn_assert(!block_index);
+
+ /* Start off with at the start of the push constant block. */
+ offset = nir_imm_int(&b->nb, 0);
} else {
/* The code above should have ensured a block_index when needed. */
vtn_assert(block_index);
@@ -662,31 +669,6 @@ vtn_type_block_size(struct vtn_builder *b, struct vtn_type *type)
}
static void
-vtn_access_chain_get_offset_size(struct vtn_builder *b,
- struct vtn_access_chain *chain,
- struct vtn_type *type,
- unsigned *access_offset,
- unsigned *access_size)
-{
- *access_offset = 0;
-
- for (unsigned i = 0; i < chain->length; i++) {
- if (chain->link[i].mode != vtn_access_mode_literal)
- break;
-
- if (glsl_type_is_struct(type->type)) {
- *access_offset += type->offsets[chain->link[i].id];
- type = type->members[chain->link[i].id];
- } else {
- *access_offset += type->stride * chain->link[i].id;
- type = type->array_element;
- }
- }
-
- *access_size = vtn_type_block_size(b, type);
-}
-
-static void
_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,
@@ -882,8 +864,7 @@ vtn_block_load(struct vtn_builder *b, struct vtn_pointer *src)
break;
case vtn_variable_mode_push_constant:
op = nir_intrinsic_load_push_constant;
- vtn_access_chain_get_offset_size(b, src->chain, src->var->type,
- &access_offset, &access_size);
+ access_size = b->shader->num_uniforms;
break;
case vtn_variable_mode_workgroup:
op = nir_intrinsic_load_shared;
@@ -1661,7 +1642,8 @@ vtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa,
ptr->offset = nir_channel(&b->nb, ssa, 1);
} else {
vtn_assert(ssa->num_components == 1);
- vtn_assert(ptr->mode == vtn_variable_mode_workgroup);
+ vtn_assert(ptr->mode == vtn_variable_mode_workgroup ||
+ ptr->mode == vtn_variable_mode_push_constant);
ptr->block_index = NULL;
ptr->offset = ssa;
}