*/
#include "pan_allocate.h"
+#include "pan_bo.h"
#include "pan_cmdstream.h"
#include "pan_context.h"
#include "pan_job.h"
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;
+}
#ifndef __PAN_CMDSTREAM_H__
#define __PAN_CMDSTREAM_H__
+#include "pipe/p_defines.h"
+
#include "panfrost-job.h"
#include "pan_job.h"
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__ */
}
}
-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;
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 */
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