From 0b735a2d808205c8a3e5e496d85693db85f7716c Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 5 Mar 2020 09:46:42 +0100 Subject: [PATCH] panfrost: Move the const buf emission logic out of panfrost_emit_for_draw() Let's move the constant buffer emission logic in a dedicated helper to make panfrost_emit_for_draw() a bit more dry. Signed-off-by: Boris Brezillon Reviewed-by: Alyssa Rosenzweig Part-of: --- src/gallium/drivers/panfrost/pan_cmdstream.c | 280 +++++++++++++++++++ src/gallium/drivers/panfrost/pan_cmdstream.h | 7 + src/gallium/drivers/panfrost/pan_context.c | 261 +---------------- src/gallium/drivers/panfrost/pan_context.h | 3 + 4 files changed, 293 insertions(+), 258 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 782957a0e9a..99b3f5eeb8b 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -23,6 +23,7 @@ */ #include "pan_allocate.h" +#include "pan_bo.h" #include "pan_cmdstream.h" #include "pan_context.h" #include "pan_job.h" @@ -142,3 +143,282 @@ panfrost_emit_viewport(struct panfrost_batch *batch, tp->postfix.viewport = panfrost_upload_transient(batch, &mvp, sizeof(mvp)); } + +static mali_ptr +panfrost_map_constant_buffer_gpu(struct panfrost_batch *batch, + enum pipe_shader_type st, + struct panfrost_constant_buffer *buf, + unsigned index) +{ + struct pipe_constant_buffer *cb = &buf->cb[index]; + struct panfrost_resource *rsrc = pan_resource(cb->buffer); + + if (rsrc) { + panfrost_batch_add_bo(batch, rsrc->bo, + PAN_BO_ACCESS_SHARED | + PAN_BO_ACCESS_READ | + panfrost_bo_access_for_stage(st)); + + /* Alignment gauranteed by + * PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT */ + return rsrc->bo->gpu + cb->buffer_offset; + } else if (cb->user_buffer) { + return panfrost_upload_transient(batch, + cb->user_buffer + + cb->buffer_offset, + cb->buffer_size); + } else { + unreachable("No constant buffer"); + } +} + +struct sysval_uniform { + union { + float f[4]; + int32_t i[4]; + uint32_t u[4]; + uint64_t du[2]; + }; +}; + +static void +panfrost_upload_viewport_scale_sysval(struct panfrost_batch *batch, + struct sysval_uniform *uniform) +{ + struct panfrost_context *ctx = batch->ctx; + const struct pipe_viewport_state *vp = &ctx->pipe_viewport; + + uniform->f[0] = vp->scale[0]; + uniform->f[1] = vp->scale[1]; + uniform->f[2] = vp->scale[2]; +} + +static void +panfrost_upload_viewport_offset_sysval(struct panfrost_batch *batch, + struct sysval_uniform *uniform) +{ + struct panfrost_context *ctx = batch->ctx; + const struct pipe_viewport_state *vp = &ctx->pipe_viewport; + + uniform->f[0] = vp->translate[0]; + uniform->f[1] = vp->translate[1]; + uniform->f[2] = vp->translate[2]; +} + +static void panfrost_upload_txs_sysval(struct panfrost_batch *batch, + enum pipe_shader_type st, + unsigned int sysvalid, + struct sysval_uniform *uniform) +{ + struct panfrost_context *ctx = batch->ctx; + unsigned texidx = PAN_SYSVAL_ID_TO_TXS_TEX_IDX(sysvalid); + unsigned dim = PAN_SYSVAL_ID_TO_TXS_DIM(sysvalid); + bool is_array = PAN_SYSVAL_ID_TO_TXS_IS_ARRAY(sysvalid); + struct pipe_sampler_view *tex = &ctx->sampler_views[st][texidx]->base; + + assert(dim); + uniform->i[0] = u_minify(tex->texture->width0, tex->u.tex.first_level); + + if (dim > 1) + uniform->i[1] = u_minify(tex->texture->height0, + tex->u.tex.first_level); + + if (dim > 2) + uniform->i[2] = u_minify(tex->texture->depth0, + tex->u.tex.first_level); + + if (is_array) + uniform->i[dim] = tex->texture->array_size; +} + +static void +panfrost_upload_ssbo_sysval(struct panfrost_batch *batch, + enum pipe_shader_type st, + unsigned ssbo_id, + struct sysval_uniform *uniform) +{ + struct panfrost_context *ctx = batch->ctx; + + assert(ctx->ssbo_mask[st] & (1 << ssbo_id)); + struct pipe_shader_buffer sb = ctx->ssbo[st][ssbo_id]; + + /* Compute address */ + struct panfrost_bo *bo = pan_resource(sb.buffer)->bo; + + panfrost_batch_add_bo(batch, bo, + PAN_BO_ACCESS_SHARED | PAN_BO_ACCESS_RW | + panfrost_bo_access_for_stage(st)); + + /* Upload address and size as sysval */ + uniform->du[0] = bo->gpu + sb.buffer_offset; + uniform->u[2] = sb.buffer_size; +} + +static void +panfrost_upload_sampler_sysval(struct panfrost_batch *batch, + enum pipe_shader_type st, + unsigned samp_idx, + struct sysval_uniform *uniform) +{ + struct panfrost_context *ctx = batch->ctx; + struct pipe_sampler_state *sampl = &ctx->samplers[st][samp_idx]->base; + + uniform->f[0] = sampl->min_lod; + uniform->f[1] = sampl->max_lod; + uniform->f[2] = sampl->lod_bias; + + /* Even without any errata, Midgard represents "no mipmapping" as + * fixing the LOD with the clamps; keep behaviour consistent. c.f. + * panfrost_create_sampler_state which also explains our choice of + * epsilon value (again to keep behaviour consistent) */ + + if (sampl->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) + uniform->f[1] = uniform->f[0] + (1.0/256.0); +} + +static void +panfrost_upload_num_work_groups_sysval(struct panfrost_batch *batch, + struct sysval_uniform *uniform) +{ + struct panfrost_context *ctx = batch->ctx; + + uniform->u[0] = ctx->compute_grid->grid[0]; + uniform->u[1] = ctx->compute_grid->grid[1]; + uniform->u[2] = ctx->compute_grid->grid[2]; +} + +static void +panfrost_upload_sysvals(struct panfrost_batch *batch, void *buf, + struct panfrost_shader_state *ss, + enum pipe_shader_type st) +{ + struct sysval_uniform *uniforms = (void *)buf; + + for (unsigned i = 0; i < ss->sysval_count; ++i) { + int sysval = ss->sysval[i]; + + switch (PAN_SYSVAL_TYPE(sysval)) { + case PAN_SYSVAL_VIEWPORT_SCALE: + panfrost_upload_viewport_scale_sysval(batch, + &uniforms[i]); + break; + case PAN_SYSVAL_VIEWPORT_OFFSET: + panfrost_upload_viewport_offset_sysval(batch, + &uniforms[i]); + break; + case PAN_SYSVAL_TEXTURE_SIZE: + panfrost_upload_txs_sysval(batch, st, + PAN_SYSVAL_ID(sysval), + &uniforms[i]); + break; + case PAN_SYSVAL_SSBO: + panfrost_upload_ssbo_sysval(batch, st, + PAN_SYSVAL_ID(sysval), + &uniforms[i]); + break; + case PAN_SYSVAL_NUM_WORK_GROUPS: + panfrost_upload_num_work_groups_sysval(batch, + &uniforms[i]); + break; + case PAN_SYSVAL_SAMPLER: + panfrost_upload_sampler_sysval(batch, st, + PAN_SYSVAL_ID(sysval), + &uniforms[i]); + break; + default: + assert(0); + } + } +} + +static const void * +panfrost_map_constant_buffer_cpu(struct panfrost_constant_buffer *buf, + unsigned index) +{ + struct pipe_constant_buffer *cb = &buf->cb[index]; + struct panfrost_resource *rsrc = pan_resource(cb->buffer); + + if (rsrc) + return rsrc->bo->cpu; + else if (cb->user_buffer) + return cb->user_buffer; + else + unreachable("No constant buffer"); +} + +void +panfrost_emit_const_buf(struct panfrost_batch *batch, + enum pipe_shader_type stage, + struct midgard_payload_vertex_tiler *vtp) +{ + struct panfrost_context *ctx = batch->ctx; + struct panfrost_shader_variants *all = ctx->shader[stage]; + + if (!all) + return; + + struct panfrost_constant_buffer *buf = &ctx->constant_buffer[stage]; + + struct panfrost_shader_state *ss = &all->variants[all->active_variant]; + + /* Uniforms are implicitly UBO #0 */ + bool has_uniforms = buf->enabled_mask & (1 << 0); + + /* Allocate room for the sysval and the uniforms */ + size_t sys_size = sizeof(float) * 4 * ss->sysval_count; + size_t uniform_size = has_uniforms ? (buf->cb[0].buffer_size) : 0; + size_t size = sys_size + uniform_size; + struct panfrost_transfer transfer = panfrost_allocate_transient(batch, + size); + + /* Upload sysvals requested by the shader */ + panfrost_upload_sysvals(batch, transfer.cpu, ss, stage); + + /* Upload uniforms */ + if (has_uniforms && uniform_size) { + const void *cpu = panfrost_map_constant_buffer_cpu(buf, 0); + memcpy(transfer.cpu + sys_size, cpu, uniform_size); + } + + struct mali_vertex_tiler_postfix *postfix = &vtp->postfix; + + /* Next up, attach UBOs. UBO #0 is the uniforms we just + * uploaded */ + + unsigned ubo_count = panfrost_ubo_count(ctx, stage); + assert(ubo_count >= 1); + + size_t sz = sizeof(uint64_t) * ubo_count; + uint64_t ubos[PAN_MAX_CONST_BUFFERS]; + int uniform_count = ss->uniform_count; + + /* Upload uniforms as a UBO */ + ubos[0] = MALI_MAKE_UBO(2 + uniform_count, transfer.gpu); + + /* The rest are honest-to-goodness UBOs */ + + for (unsigned ubo = 1; ubo < ubo_count; ++ubo) { + size_t usz = buf->cb[ubo].buffer_size; + bool enabled = buf->enabled_mask & (1 << ubo); + bool empty = usz == 0; + + if (!enabled || empty) { + /* Stub out disabled UBOs to catch accesses */ + ubos[ubo] = MALI_MAKE_UBO(0, 0xDEAD0000); + continue; + } + + mali_ptr gpu = panfrost_map_constant_buffer_gpu(batch, stage, + buf, ubo); + + unsigned bytes_per_field = 16; + unsigned aligned = ALIGN_POT(usz, bytes_per_field); + ubos[ubo] = MALI_MAKE_UBO(aligned / bytes_per_field, gpu); + } + + mali_ptr ubufs = panfrost_upload_transient(batch, ubos, sz); + postfix->uniforms = transfer.gpu; + postfix->uniform_buffers = ubufs; + + buf->dirty_mask = 0; +} diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.h b/src/gallium/drivers/panfrost/pan_cmdstream.h index 223c0e66cd7..a9efca75e50 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.h +++ b/src/gallium/drivers/panfrost/pan_cmdstream.h @@ -25,6 +25,8 @@ #ifndef __PAN_CMDSTREAM_H__ #define __PAN_CMDSTREAM_H__ +#include "pipe/p_defines.h" + #include "panfrost-job.h" #include "pan_job.h" @@ -33,4 +35,9 @@ void panfrost_emit_viewport(struct panfrost_batch *batch, struct midgard_payload_vertex_tiler *tp); +void +panfrost_emit_const_buf(struct panfrost_batch *batch, + enum pipe_shader_type stage, + struct midgard_payload_vertex_tiler *vtp); + #endif /* __PAN_CMDSTREAM_H__ */ diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index 85b35d77bcb..a79da05603f 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -518,196 +518,12 @@ panfrost_upload_texture_descriptors(struct panfrost_context *ctx) } } -struct sysval_uniform { - union { - float f[4]; - int32_t i[4]; - uint32_t u[4]; - uint64_t du[2]; - }; -}; - -static void panfrost_upload_viewport_scale_sysval(struct panfrost_context *ctx, - struct sysval_uniform *uniform) -{ - const struct pipe_viewport_state *vp = &ctx->pipe_viewport; - - uniform->f[0] = vp->scale[0]; - uniform->f[1] = vp->scale[1]; - uniform->f[2] = vp->scale[2]; -} - -static void panfrost_upload_viewport_offset_sysval(struct panfrost_context *ctx, - struct sysval_uniform *uniform) -{ - const struct pipe_viewport_state *vp = &ctx->pipe_viewport; - - uniform->f[0] = vp->translate[0]; - uniform->f[1] = vp->translate[1]; - uniform->f[2] = vp->translate[2]; -} - -static void panfrost_upload_txs_sysval(struct panfrost_context *ctx, - enum pipe_shader_type st, - unsigned int sysvalid, - struct sysval_uniform *uniform) -{ - unsigned texidx = PAN_SYSVAL_ID_TO_TXS_TEX_IDX(sysvalid); - unsigned dim = PAN_SYSVAL_ID_TO_TXS_DIM(sysvalid); - bool is_array = PAN_SYSVAL_ID_TO_TXS_IS_ARRAY(sysvalid); - struct pipe_sampler_view *tex = &ctx->sampler_views[st][texidx]->base; - - assert(dim); - uniform->i[0] = u_minify(tex->texture->width0, tex->u.tex.first_level); - - if (dim > 1) - uniform->i[1] = u_minify(tex->texture->height0, - tex->u.tex.first_level); - - if (dim > 2) - uniform->i[2] = u_minify(tex->texture->depth0, - tex->u.tex.first_level); - - if (is_array) - uniform->i[dim] = tex->texture->array_size; -} - -static void panfrost_upload_ssbo_sysval( - struct panfrost_context *ctx, - enum pipe_shader_type st, - unsigned ssbo_id, - struct sysval_uniform *uniform) -{ - assert(ctx->ssbo_mask[st] & (1 << ssbo_id)); - struct pipe_shader_buffer sb = ctx->ssbo[st][ssbo_id]; - - /* Compute address */ - struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx); - struct panfrost_bo *bo = pan_resource(sb.buffer)->bo; - - panfrost_batch_add_bo(batch, bo, - PAN_BO_ACCESS_SHARED | PAN_BO_ACCESS_RW | - panfrost_bo_access_for_stage(st)); - - /* Upload address and size as sysval */ - uniform->du[0] = bo->gpu + sb.buffer_offset; - uniform->u[2] = sb.buffer_size; -} - -static void -panfrost_upload_sampler_sysval( - struct panfrost_context *ctx, - enum pipe_shader_type st, - unsigned sampler_index, - struct sysval_uniform *uniform) -{ - struct pipe_sampler_state *sampl = - &ctx->samplers[st][sampler_index]->base; - - uniform->f[0] = sampl->min_lod; - uniform->f[1] = sampl->max_lod; - uniform->f[2] = sampl->lod_bias; - - /* Even without any errata, Midgard represents "no mipmapping" as - * fixing the LOD with the clamps; keep behaviour consistent. c.f. - * panfrost_create_sampler_state which also explains our choice of - * epsilon value (again to keep behaviour consistent) */ - - if (sampl->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) - uniform->f[1] = uniform->f[0] + (1.0/256.0); -} - -static void panfrost_upload_num_work_groups_sysval(struct panfrost_context *ctx, - struct sysval_uniform *uniform) -{ - uniform->u[0] = ctx->compute_grid->grid[0]; - uniform->u[1] = ctx->compute_grid->grid[1]; - uniform->u[2] = ctx->compute_grid->grid[2]; -} - -static void panfrost_upload_sysvals(struct panfrost_context *ctx, void *buf, - struct panfrost_shader_state *ss, - enum pipe_shader_type st) -{ - struct sysval_uniform *uniforms = (void *)buf; - - for (unsigned i = 0; i < ss->sysval_count; ++i) { - int sysval = ss->sysval[i]; - - switch (PAN_SYSVAL_TYPE(sysval)) { - case PAN_SYSVAL_VIEWPORT_SCALE: - panfrost_upload_viewport_scale_sysval(ctx, &uniforms[i]); - break; - case PAN_SYSVAL_VIEWPORT_OFFSET: - panfrost_upload_viewport_offset_sysval(ctx, &uniforms[i]); - break; - case PAN_SYSVAL_TEXTURE_SIZE: - panfrost_upload_txs_sysval(ctx, st, PAN_SYSVAL_ID(sysval), - &uniforms[i]); - break; - case PAN_SYSVAL_SSBO: - panfrost_upload_ssbo_sysval(ctx, st, PAN_SYSVAL_ID(sysval), - &uniforms[i]); - break; - case PAN_SYSVAL_NUM_WORK_GROUPS: - panfrost_upload_num_work_groups_sysval(ctx, &uniforms[i]); - break; - case PAN_SYSVAL_SAMPLER: - panfrost_upload_sampler_sysval(ctx, st, PAN_SYSVAL_ID(sysval), - &uniforms[i]); - break; - default: - assert(0); - } - } -} - -static const void * -panfrost_map_constant_buffer_cpu(struct panfrost_constant_buffer *buf, unsigned index) -{ - struct pipe_constant_buffer *cb = &buf->cb[index]; - struct panfrost_resource *rsrc = pan_resource(cb->buffer); - - if (rsrc) - return rsrc->bo->cpu; - else if (cb->user_buffer) - return cb->user_buffer; - else - unreachable("No constant buffer"); -} - -static mali_ptr -panfrost_map_constant_buffer_gpu( - struct panfrost_context *ctx, - enum pipe_shader_type st, - struct panfrost_constant_buffer *buf, - unsigned index) -{ - struct pipe_constant_buffer *cb = &buf->cb[index]; - struct panfrost_resource *rsrc = pan_resource(cb->buffer); - struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx); - - if (rsrc) { - panfrost_batch_add_bo(batch, rsrc->bo, - PAN_BO_ACCESS_SHARED | - PAN_BO_ACCESS_READ | - panfrost_bo_access_for_stage(st)); - - /* Alignment gauranteed by PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT */ - return rsrc->bo->gpu + cb->buffer_offset; - } else if (cb->user_buffer) { - return panfrost_upload_transient(batch, cb->user_buffer + cb->buffer_offset, cb->buffer_size); - } else { - unreachable("No constant buffer"); - } -} - /* Compute number of UBOs active (more specifically, compute the highest UBO * number addressable -- if there are gaps, include them in the count anyway). * We always include UBO #0 in the count, since we *need* uniforms enabled for * sysvals. */ -static unsigned +unsigned panfrost_ubo_count(struct panfrost_context *ctx, enum pipe_shader_type stage) { unsigned mask = ctx->constant_buffer[stage].enabled_mask | 1; @@ -953,79 +769,8 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) panfrost_upload_sampler_descriptors(ctx); panfrost_upload_texture_descriptors(ctx); - for (int i = 0; i < PIPE_SHADER_TYPES; ++i) { - struct panfrost_shader_variants *all = ctx->shader[i]; - - if (!all) - continue; - - struct panfrost_constant_buffer *buf = &ctx->constant_buffer[i]; - - struct panfrost_shader_state *ss = &all->variants[all->active_variant]; - - /* Uniforms are implicitly UBO #0 */ - bool has_uniforms = buf->enabled_mask & (1 << 0); - - /* Allocate room for the sysval and the uniforms */ - size_t sys_size = sizeof(float) * 4 * ss->sysval_count; - size_t uniform_size = has_uniforms ? (buf->cb[0].buffer_size) : 0; - size_t size = sys_size + uniform_size; - struct panfrost_transfer transfer = panfrost_allocate_transient(batch, size); - - /* Upload sysvals requested by the shader */ - panfrost_upload_sysvals(ctx, transfer.cpu, ss, i); - - /* Upload uniforms */ - if (has_uniforms && uniform_size) { - const void *cpu = panfrost_map_constant_buffer_cpu(buf, 0); - memcpy(transfer.cpu + sys_size, cpu, uniform_size); - } - - int uniform_count = - ctx->shader[i]->variants[ctx->shader[i]->active_variant].uniform_count; - - struct mali_vertex_tiler_postfix *postfix = - &ctx->payloads[i].postfix; - - /* Next up, attach UBOs. UBO #0 is the uniforms we just - * uploaded */ - - unsigned ubo_count = panfrost_ubo_count(ctx, i); - assert(ubo_count >= 1); - - size_t sz = sizeof(uint64_t) * ubo_count; - uint64_t ubos[PAN_MAX_CONST_BUFFERS]; - - /* Upload uniforms as a UBO */ - ubos[0] = MALI_MAKE_UBO(2 + uniform_count, transfer.gpu); - - /* The rest are honest-to-goodness UBOs */ - - for (unsigned ubo = 1; ubo < ubo_count; ++ubo) { - size_t usz = buf->cb[ubo].buffer_size; - - bool enabled = buf->enabled_mask & (1 << ubo); - bool empty = usz == 0; - - if (!enabled || empty) { - /* Stub out disabled UBOs to catch accesses */ - ubos[ubo] = MALI_MAKE_UBO(0, 0xDEAD0000); - continue; - } - - mali_ptr gpu = panfrost_map_constant_buffer_gpu(ctx, i, buf, ubo); - - unsigned bytes_per_field = 16; - unsigned aligned = ALIGN_POT(usz, bytes_per_field); - ubos[ubo] = MALI_MAKE_UBO(aligned / bytes_per_field, gpu); - } - - mali_ptr ubufs = panfrost_upload_transient(batch, ubos, sz); - postfix->uniforms = transfer.gpu; - postfix->uniform_buffers = ubufs; - - buf->dirty_mask = 0; - } + for (int i = 0; i < PIPE_SHADER_TYPES; ++i) + panfrost_emit_const_buf(batch, i, &ctx->payloads[i]); /* TODO: Upload the viewport somewhere more appropriate */ diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h index 5fe8aebe960..2bb81203f15 100644 --- a/src/gallium/drivers/panfrost/pan_context.h +++ b/src/gallium/drivers/panfrost/pan_context.h @@ -330,6 +330,9 @@ panfrost_shader_compile( struct panfrost_shader_state *state, uint64_t *outputs_written); +unsigned +panfrost_ubo_count(struct panfrost_context *ctx, enum pipe_shader_type stage); + /* Instancing */ mali_ptr -- 2.30.2