nir/spirv: Implement OpPtrAccessChain for buffers
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
This commit is contained in:
@@ -600,7 +600,8 @@ type_decoration_cb(struct vtn_builder *b,
|
|||||||
switch (dec->decoration) {
|
switch (dec->decoration) {
|
||||||
case SpvDecorationArrayStride:
|
case SpvDecorationArrayStride:
|
||||||
assert(type->base_type == vtn_base_type_matrix ||
|
assert(type->base_type == vtn_base_type_matrix ||
|
||||||
type->base_type == vtn_base_type_array);
|
type->base_type == vtn_base_type_array ||
|
||||||
|
type->base_type == vtn_base_type_pointer);
|
||||||
type->stride = dec->literals[0];
|
type->stride = dec->literals[0];
|
||||||
break;
|
break;
|
||||||
case SpvDecorationBlock:
|
case SpvDecorationBlock:
|
||||||
@@ -3067,6 +3068,7 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode,
|
|||||||
case SpvOpCopyMemory:
|
case SpvOpCopyMemory:
|
||||||
case SpvOpCopyMemorySized:
|
case SpvOpCopyMemorySized:
|
||||||
case SpvOpAccessChain:
|
case SpvOpAccessChain:
|
||||||
|
case SpvOpPtrAccessChain:
|
||||||
case SpvOpInBoundsAccessChain:
|
case SpvOpInBoundsAccessChain:
|
||||||
case SpvOpArrayLength:
|
case SpvOpArrayLength:
|
||||||
vtn_handle_variables(b, opcode, w, count);
|
vtn_handle_variables(b, opcode, w, count);
|
||||||
|
@@ -220,15 +220,15 @@ struct vtn_type {
|
|||||||
/* Specifies the length of complex types. */
|
/* Specifies the length of complex types. */
|
||||||
unsigned length;
|
unsigned length;
|
||||||
|
|
||||||
|
/* for arrays, matrices and pointers, the array stride */
|
||||||
|
unsigned stride;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
/* Members for scalar, vector, and array-like types */
|
/* Members for scalar, vector, and array-like types */
|
||||||
struct {
|
struct {
|
||||||
/* for arrays, the vtn_type for the elements of the array */
|
/* for arrays, the vtn_type for the elements of the array */
|
||||||
struct vtn_type *array_element;
|
struct vtn_type *array_element;
|
||||||
|
|
||||||
/* for arrays and matrices, the array stride */
|
|
||||||
unsigned stride;
|
|
||||||
|
|
||||||
/* for matrices, whether the matrix is stored row-major */
|
/* for matrices, whether the matrix is stored row-major */
|
||||||
bool row_major:1;
|
bool row_major:1;
|
||||||
|
|
||||||
@@ -308,6 +308,11 @@ struct vtn_access_link {
|
|||||||
struct vtn_access_chain {
|
struct vtn_access_chain {
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
|
|
||||||
|
/** Whether or not to treat the base pointer as an array. This is only
|
||||||
|
* true if this access chain came from an OpPtrAccessChain.
|
||||||
|
*/
|
||||||
|
bool ptr_as_array;
|
||||||
|
|
||||||
/** Struct elements and array offsets.
|
/** Struct elements and array offsets.
|
||||||
*
|
*
|
||||||
* This is an array of 1 so that it can conveniently be created on the
|
* This is an array of 1 so that it can conveniently be created on the
|
||||||
|
@@ -67,6 +67,12 @@ vtn_access_chain_pointer_dereference(struct vtn_builder *b,
|
|||||||
vtn_access_chain_extend(b, base->chain, deref_chain->length);
|
vtn_access_chain_extend(b, base->chain, deref_chain->length);
|
||||||
struct vtn_type *type = base->type;
|
struct vtn_type *type = base->type;
|
||||||
|
|
||||||
|
/* OpPtrAccessChain is only allowed on things which support variable
|
||||||
|
* pointers. For everything else, the client is expected to just pass us
|
||||||
|
* the right access chain.
|
||||||
|
*/
|
||||||
|
assert(!deref_chain->ptr_as_array);
|
||||||
|
|
||||||
unsigned start = base->chain ? base->chain->length : 0;
|
unsigned start = base->chain ? base->chain->length : 0;
|
||||||
for (unsigned i = 0; i < deref_chain->length; i++) {
|
for (unsigned i = 0; i < deref_chain->length; i++) {
|
||||||
chain->link[start + i] = deref_chain->link[i];
|
chain->link[start + i] = deref_chain->link[i];
|
||||||
@@ -135,6 +141,21 @@ vtn_ssa_offset_pointer_dereference(struct vtn_builder *b,
|
|||||||
struct vtn_type *type = base->type;
|
struct vtn_type *type = base->type;
|
||||||
|
|
||||||
unsigned idx = 0;
|
unsigned idx = 0;
|
||||||
|
if (deref_chain->ptr_as_array) {
|
||||||
|
/* We need ptr_type for the stride */
|
||||||
|
assert(base->ptr_type);
|
||||||
|
/* This must be a pointer to an actual element somewhere */
|
||||||
|
assert(block_index && offset);
|
||||||
|
/* We need at least one element in the chain */
|
||||||
|
assert(deref_chain->length >= 1);
|
||||||
|
|
||||||
|
nir_ssa_def *elem_offset =
|
||||||
|
vtn_access_link_as_ssa(b, deref_chain->link[idx],
|
||||||
|
base->ptr_type->stride);
|
||||||
|
offset = nir_iadd(&b->nb, offset, elem_offset);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
if (!block_index) {
|
if (!block_index) {
|
||||||
assert(base->var);
|
assert(base->var);
|
||||||
if (glsl_type_is_array(type->type)) {
|
if (glsl_type_is_array(type->type)) {
|
||||||
@@ -1699,8 +1720,10 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case SpvOpAccessChain:
|
case SpvOpAccessChain:
|
||||||
|
case SpvOpPtrAccessChain:
|
||||||
case SpvOpInBoundsAccessChain: {
|
case SpvOpInBoundsAccessChain: {
|
||||||
struct vtn_access_chain *chain = vtn_access_chain_create(b, count - 4);
|
struct vtn_access_chain *chain = vtn_access_chain_create(b, count - 4);
|
||||||
|
chain->ptr_as_array = (opcode == SpvOpPtrAccessChain);
|
||||||
|
|
||||||
unsigned idx = 0;
|
unsigned idx = 0;
|
||||||
for (int i = 4; i < count; i++) {
|
for (int i = 4; i < count; i++) {
|
||||||
|
Reference in New Issue
Block a user