pan/bi: Add support for gl_{BaseVertex,BaseInstance}
Extend the VERTEX_INSTANCE_OFFSETS sysval to pass BaseVertex/BaseInstance information to the shader. Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Acked-by: Alyssa Rosenzweig <alyssa@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10417>
This commit is contained in:
parent
69d81edaf8
commit
7cc4c8c5e5
|
@ -1083,8 +1083,14 @@ panfrost_upload_sysvals(struct panfrost_batch *batch,
|
|||
case PAN_SYSVAL_VERTEX_INSTANCE_OFFSETS:
|
||||
batch->ctx->first_vertex_sysval_ptr =
|
||||
ptr->gpu + (i * sizeof(*uniforms));
|
||||
batch->ctx->base_vertex_sysval_ptr =
|
||||
batch->ctx->first_vertex_sysval_ptr + 4;
|
||||
batch->ctx->base_instance_sysval_ptr =
|
||||
batch->ctx->first_vertex_sysval_ptr + 8;
|
||||
|
||||
uniforms[i].u[0] = batch->ctx->offset_start;
|
||||
uniforms[i].u[1] = batch->ctx->base_vertex;
|
||||
uniforms[i].u[2] = batch->ctx->base_instance;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
@ -1200,6 +1206,12 @@ panfrost_emit_const_buf(struct panfrost_batch *batch,
|
|||
case 0:
|
||||
batch->ctx->first_vertex_sysval_ptr = ptr;
|
||||
break;
|
||||
case 1:
|
||||
batch->ctx->base_vertex_sysval_ptr = ptr;
|
||||
break;
|
||||
case 2:
|
||||
batch->ctx->base_instance_sysval_ptr = ptr;
|
||||
break;
|
||||
default:
|
||||
unreachable("Invalid vertex/instance offset component\n");
|
||||
}
|
||||
|
@ -1730,6 +1742,12 @@ panfrost_emit_vertex_data(struct panfrost_batch *batch,
|
|||
/* BOs aligned to 4k so guaranteed aligned to 64 */
|
||||
src_offset += (buf->buffer_offset & 63);
|
||||
|
||||
/* Base instance offset */
|
||||
if (ctx->base_instance && so->pipe[i].instance_divisor) {
|
||||
src_offset += (ctx->base_instance * buf->stride) /
|
||||
so->pipe[i].instance_divisor;
|
||||
}
|
||||
|
||||
/* Also, somewhat obscurely per-instance data needs to be
|
||||
* offset in response to a delayed start in an indexed draw */
|
||||
|
||||
|
|
|
@ -450,6 +450,8 @@ panfrost_direct_draw(struct panfrost_context *ctx,
|
|||
ctx->indirect_draw = false;
|
||||
ctx->vertex_count = draw->count + (info->index_size ? abs(draw->index_bias) : 0);
|
||||
ctx->instance_count = info->instance_count;
|
||||
ctx->base_vertex = info->index_size ? draw->index_bias : 0;
|
||||
ctx->base_instance = info->start_instance;
|
||||
ctx->active_prim = info->mode;
|
||||
|
||||
struct panfrost_ptr tiler =
|
||||
|
@ -613,6 +615,9 @@ panfrost_indirect_draw(struct panfrost_context *ctx,
|
|||
* vertex shader uses gl_VertexID or gl_BaseVertex.
|
||||
*/
|
||||
ctx->first_vertex_sysval_ptr = 0;
|
||||
ctx->base_vertex_sysval_ptr = 0;
|
||||
ctx->base_instance_sysval_ptr = 0;
|
||||
|
||||
bool point_coord_replace = (info->mode == PIPE_PRIM_POINTS);
|
||||
|
||||
panfrost_emit_varying_descriptor(batch, 0,
|
||||
|
@ -660,6 +665,8 @@ panfrost_indirect_draw(struct panfrost_context *ctx,
|
|||
.draw_buf = draw_buf->image.data.bo->ptr.gpu + indirect->offset,
|
||||
.index_buf = index_buf ? index_buf->ptr.gpu : 0,
|
||||
.first_vertex_sysval = ctx->first_vertex_sysval_ptr,
|
||||
.base_vertex_sysval = ctx->base_vertex_sysval_ptr,
|
||||
.base_instance_sysval = ctx->base_instance_sysval_ptr,
|
||||
.vertex_job = vertex.gpu,
|
||||
.tiler_job = tiler.gpu,
|
||||
.attrib_bufs = attrib_bufs,
|
||||
|
|
|
@ -137,7 +137,11 @@ struct panfrost_context {
|
|||
unsigned vertex_count;
|
||||
unsigned instance_count;
|
||||
unsigned offset_start;
|
||||
unsigned base_vertex;
|
||||
unsigned base_instance;
|
||||
mali_ptr first_vertex_sysval_ptr;
|
||||
mali_ptr base_vertex_sysval_ptr;
|
||||
mali_ptr base_instance_sysval_ptr;
|
||||
enum pipe_prim_type active_prim;
|
||||
|
||||
/* If instancing is enabled, vertex count padded for instance; if
|
||||
|
|
|
@ -310,6 +310,9 @@ panfrost_get_param(struct pipe_screen *screen, enum pipe_cap param)
|
|||
case PIPE_CAP_DRAW_INDIRECT:
|
||||
return has_heap && is_deqp;
|
||||
|
||||
case PIPE_CAP_START_INSTANCE:
|
||||
return pan_is_bifrost(dev) && is_deqp;
|
||||
|
||||
default:
|
||||
return u_pipe_screen_get_param_defaults(screen, param);
|
||||
}
|
||||
|
|
|
@ -1158,6 +1158,14 @@ bi_emit_intrinsic(bi_builder *b, nir_intrinsic_instr *instr)
|
|||
bi_load_sysval_nir(b, instr, 1, 0);
|
||||
break;
|
||||
|
||||
case nir_intrinsic_load_base_vertex:
|
||||
bi_load_sysval_nir(b, instr, 1, 4);
|
||||
break;
|
||||
|
||||
case nir_intrinsic_load_base_instance:
|
||||
bi_load_sysval_nir(b, instr, 1, 8);
|
||||
break;
|
||||
|
||||
case nir_intrinsic_get_ssbo_size:
|
||||
bi_load_sysval_nir(b, instr, 1, 8);
|
||||
break;
|
||||
|
|
|
@ -55,6 +55,7 @@ struct draw_data {
|
|||
nir_ssa_def *index_buf;
|
||||
nir_ssa_def *restart_index;
|
||||
nir_ssa_def *vertex_count;
|
||||
nir_ssa_def *start_instance;
|
||||
nir_ssa_def *instance_count;
|
||||
nir_ssa_def *vertex_start;
|
||||
nir_ssa_def *index_bias;
|
||||
|
@ -73,6 +74,8 @@ struct jobs_data {
|
|||
nir_ssa_def *tiler_job;
|
||||
nir_ssa_def *base_vertex_offset;
|
||||
nir_ssa_def *first_vertex_sysval;
|
||||
nir_ssa_def *base_vertex_sysval;
|
||||
nir_ssa_def *base_instance_sysval;
|
||||
nir_ssa_def *offset_start;
|
||||
nir_ssa_def *invocation;
|
||||
};
|
||||
|
@ -160,6 +163,9 @@ struct indirect_draw_inputs {
|
|||
|
||||
/* {base,first}_{vertex,instance} sysvals */
|
||||
mali_ptr first_vertex_sysval;
|
||||
mali_ptr base_vertex_sysval;
|
||||
mali_ptr base_instance_sysval;
|
||||
|
||||
/* Pointers to various cmdstream structs that need to be patched */
|
||||
mali_ptr vertex_job;
|
||||
mali_ptr tiler_job;
|
||||
|
@ -318,6 +324,8 @@ extract_inputs(struct indirect_draw_shader_builder *builder)
|
|||
return;
|
||||
|
||||
builder->jobs.first_vertex_sysval = get_input_field(b, first_vertex_sysval);
|
||||
builder->jobs.base_vertex_sysval = get_input_field(b, base_vertex_sysval);
|
||||
builder->jobs.base_instance_sysval = get_input_field(b, base_instance_sysval);
|
||||
builder->jobs.vertex_job = get_input_field(b, vertex_job);
|
||||
builder->jobs.tiler_job = get_input_field(b, tiler_job);
|
||||
builder->attribs.attrib_bufs = get_input_field(b, attrib_bufs);
|
||||
|
@ -506,7 +514,8 @@ update_vertex_attrib_buf(struct indirect_draw_shader_builder *builder,
|
|||
|
||||
static void
|
||||
adjust_attrib_offset(struct indirect_draw_shader_builder *builder,
|
||||
nir_ssa_def *attrib_ptr, nir_ssa_def *attrib_buf_ptr)
|
||||
nir_ssa_def *attrib_ptr, nir_ssa_def *attrib_buf_ptr,
|
||||
nir_ssa_def *instance_div)
|
||||
{
|
||||
nir_builder *b = &builder->b;
|
||||
nir_ssa_def *zero = nir_imm_int(b, 0);
|
||||
|
@ -515,18 +524,34 @@ adjust_attrib_offset(struct indirect_draw_shader_builder *builder,
|
|||
nir_iand(b, nir_ine(b, builder->jobs.offset_start, zero),
|
||||
nir_ige(b, builder->draw.instance_count, two));
|
||||
|
||||
IF (sub_cur_offset) {
|
||||
nir_ssa_def *add_base_inst_offset =
|
||||
nir_iand(b, nir_ine(b, builder->draw.start_instance, zero),
|
||||
nir_ine(b, instance_div, zero));
|
||||
|
||||
IF (nir_ior(b, sub_cur_offset, add_base_inst_offset)) {
|
||||
nir_ssa_def *offset =
|
||||
load_global(b, get_address_imm(b, attrib_ptr, WORD(1)), 1, 32);
|
||||
nir_ssa_def *stride =
|
||||
load_global(b, get_address_imm(b, attrib_buf_ptr, WORD(2)), 1, 32);
|
||||
|
||||
/* Per-instance data needs to be offset in response to a
|
||||
* delayed start in an indexed draw.
|
||||
*/
|
||||
nir_ssa_def *stride =
|
||||
load_global(b, get_address_imm(b, attrib_buf_ptr, WORD(2)), 1, 32);
|
||||
nir_ssa_def *offset =
|
||||
load_global(b, get_address_imm(b, attrib_ptr, WORD(1)), 1, 32);
|
||||
|
||||
offset = nir_isub(b, offset,
|
||||
nir_imul(b, stride,
|
||||
builder->jobs.offset_start));
|
||||
IF (add_base_inst_offset) {
|
||||
offset = nir_iadd(b, offset,
|
||||
nir_idiv(b,
|
||||
nir_imul(b, stride,
|
||||
builder->draw.start_instance),
|
||||
instance_div));
|
||||
} ENDIF
|
||||
|
||||
IF (sub_cur_offset) {
|
||||
offset = nir_isub(b, offset,
|
||||
nir_imul(b, stride,
|
||||
builder->jobs.offset_start));
|
||||
} ENDIF
|
||||
|
||||
store_global(b, get_address_imm(b, attrib_ptr, WORD(1)),
|
||||
offset, 1);
|
||||
} ENDIF
|
||||
|
@ -600,10 +625,10 @@ update_vertex_attribs(struct indirect_draw_shader_builder *builder)
|
|||
} ENDIF
|
||||
}
|
||||
|
||||
nir_ssa_def *div =
|
||||
nir_ssa_def *instance_div =
|
||||
load_global(b, get_address_imm(b, attrib_buf_ptr, WORD(7)), 1, 32);
|
||||
|
||||
div = nir_imul(b, div, builder->instance_size.padded);
|
||||
nir_ssa_def *div = nir_imul(b, instance_div, builder->instance_size.padded);
|
||||
|
||||
nir_ssa_def *multi_instance =
|
||||
nir_ige(b, builder->draw.instance_count, nir_imm_int(b, 2));
|
||||
|
@ -636,7 +661,7 @@ update_vertex_attribs(struct indirect_draw_shader_builder *builder)
|
|||
nir_imm_int(b, 31), NULL);
|
||||
} ENDIF
|
||||
|
||||
adjust_attrib_offset(builder, attrib_ptr, attrib_buf_ptr);
|
||||
adjust_attrib_offset(builder, attrib_ptr, attrib_buf_ptr, instance_div);
|
||||
} ELSE {
|
||||
IF (multi_instance) {
|
||||
update_vertex_attrib_buf(builder, attrib_buf_ptr,
|
||||
|
@ -888,12 +913,14 @@ patch(struct indirect_draw_shader_builder *builder)
|
|||
|
||||
if (index_size) {
|
||||
builder->draw.vertex_count = get_indexed_draw_field(b, draw_ptr, count);
|
||||
builder->draw.start_instance = get_indexed_draw_field(b, draw_ptr, start_instance);
|
||||
builder->draw.instance_count =
|
||||
get_indexed_draw_field(b, draw_ptr, instance_count);
|
||||
builder->draw.vertex_start = get_indexed_draw_field(b, draw_ptr, start);
|
||||
builder->draw.index_bias = get_indexed_draw_field(b, draw_ptr, index_bias);
|
||||
} else {
|
||||
builder->draw.vertex_count = get_draw_field(b, draw_ptr, count);
|
||||
builder->draw.start_instance = get_draw_field(b, draw_ptr, start_instance);
|
||||
builder->draw.instance_count = get_draw_field(b, draw_ptr, instance_count);
|
||||
builder->draw.vertex_start = get_draw_field(b, draw_ptr, start);
|
||||
}
|
||||
|
@ -914,6 +941,20 @@ patch(struct indirect_draw_shader_builder *builder)
|
|||
store_global(b, builder->jobs.first_vertex_sysval,
|
||||
builder->jobs.offset_start, 1);
|
||||
} ENDIF
|
||||
|
||||
IF (nir_ine(b, builder->jobs.base_vertex_sysval, nir_imm_int64(b, 0))) {
|
||||
store_global(b, builder->jobs.base_vertex_sysval,
|
||||
index_size ?
|
||||
builder->draw.index_bias :
|
||||
nir_imm_int(b, 0),
|
||||
1);
|
||||
} ENDIF
|
||||
|
||||
IF (nir_ine(b, builder->jobs.base_instance_sysval, nir_imm_int64(b, 0))) {
|
||||
store_global(b, builder->jobs.base_instance_sysval,
|
||||
builder->draw.start_instance, 1);
|
||||
} ENDIF
|
||||
|
||||
}
|
||||
|
||||
/* Search the min/max index in the range covered by the indirect draw call */
|
||||
|
@ -1255,6 +1296,8 @@ panfrost_emit_indirect_draw(struct pan_pool *pool,
|
|||
.draw_buf = draw_info->draw_buf,
|
||||
.index_buf = draw_info->index_buf,
|
||||
.first_vertex_sysval = draw_info->first_vertex_sysval,
|
||||
.base_vertex_sysval = draw_info->base_vertex_sysval,
|
||||
.base_instance_sysval = draw_info->base_instance_sysval,
|
||||
.vertex_job = draw_info->vertex_job,
|
||||
.tiler_job = draw_info->tiler_job,
|
||||
.attrib_bufs = draw_info->attrib_bufs,
|
||||
|
|
|
@ -32,6 +32,8 @@ struct pan_indirect_draw_info {
|
|||
mali_ptr draw_buf;
|
||||
mali_ptr index_buf;
|
||||
mali_ptr first_vertex_sysval;
|
||||
mali_ptr base_vertex_sysval;
|
||||
mali_ptr base_instance_sysval;
|
||||
mali_ptr vertex_job;
|
||||
mali_ptr tiler_job;
|
||||
mali_ptr attrib_bufs;
|
||||
|
|
|
@ -79,6 +79,8 @@ panfrost_nir_sysval_for_intrinsic(nir_intrinsic_instr *instr)
|
|||
case nir_intrinsic_load_sample_positions_pan:
|
||||
return PAN_SYSVAL_SAMPLE_POSITIONS;
|
||||
case nir_intrinsic_load_first_vertex:
|
||||
case nir_intrinsic_load_base_vertex:
|
||||
case nir_intrinsic_load_base_instance:
|
||||
return PAN_SYSVAL_VERTEX_INSTANCE_OFFSETS;
|
||||
case nir_intrinsic_load_ssbo_address:
|
||||
case nir_intrinsic_get_ssbo_size:
|
||||
|
|
Loading…
Reference in New Issue