X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fpanfrost%2Fpan_context.c;h=de6dd38c5566b8d77ed38bc22e952f0dcb172e13;hb=b670becb1ea00a8aafd30b56521e9e93b10c0e85;hp=470a259419b664cac2674c3cd9e86025e78be501;hpb=b5db7cce607c3c94b703e67e3c847ef07c35e058;p=mesa.git diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index 470a259419b..de6dd38c556 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -26,7 +26,6 @@ #include #include "pan_context.h" -#include "pan_swizzle.h" #include "pan_format.h" #include "util/macros.h" @@ -48,9 +47,6 @@ #include "pan_util.h" #include "pan_tiler.h" -static int performance_counter_number = 0; -extern const char *pan_counters_base; - /* Do not actually send anything to the GPU; merely generate the cmdstream as fast as possible. Disables framebuffer writes */ //#define DRY_RUN @@ -90,7 +86,7 @@ panfrost_enable_checksum(struct panfrost_context *ctx, struct panfrost_resource /* 8 byte checksum per tile */ rsrc->bo->checksum_stride = tile_w * 8; int pages = (((rsrc->bo->checksum_stride * tile_h) + 4095) / 4096); - screen->driver->allocate_slab(screen, &rsrc->bo->checksum_slab, pages, false, 0, 0, 0); + panfrost_drm_allocate_slab(screen, &rsrc->bo->checksum_slab, pages, false, 0, 0, 0); rsrc->bo->has_checksum = true; } @@ -518,15 +514,6 @@ panfrost_default_shader_backend(struct panfrost_context *ctx) memcpy(&ctx->fragment_shader_core, &shader, sizeof(shader)); } -static void -panfrost_link_job_pair(struct mali_job_descriptor_header *first, mali_ptr next) -{ - if (first->job_descriptor_size) - first->next_job_64 = (u64) (uintptr_t) next; - else - first->next_job_32 = (u32) (uintptr_t) next; -} - /* Generates a vertex/tiler job. This is, in some sense, the heart of the * graphics command stream. It should be called once per draw, accordding to * presentations. Set is_tiler for "tiler" jobs (fragment shader jobs, but in @@ -536,12 +523,8 @@ panfrost_link_job_pair(struct mali_job_descriptor_header *first, mali_ptr next) struct panfrost_transfer panfrost_vertex_tiler_job(struct panfrost_context *ctx, bool is_tiler) { - /* Each draw call corresponds to two jobs, and the set-value job is first */ - int draw_job_index = 1 + (2 * ctx->draw_count) + 1; - struct mali_job_descriptor_header job = { .job_type = is_tiler ? JOB_TYPE_TILER : JOB_TYPE_VERTEX, - .job_index = draw_job_index + (is_tiler ? 1 : 0), #ifdef __LP64__ .job_descriptor_size = 1, #endif @@ -558,65 +541,11 @@ panfrost_vertex_tiler_job(struct panfrost_context *ctx, bool is_tiler) #endif struct panfrost_transfer transfer = panfrost_allocate_transient(ctx, sizeof(job) + sizeof(*payload)); - if (is_tiler) { - /* Tiler jobs depend on vertex jobs */ - - job.job_dependency_index_1 = draw_job_index; - - /* Tiler jobs also depend on the previous tiler job */ - - if (ctx->draw_count) { - job.job_dependency_index_2 = draw_job_index - 1; - /* Previous tiler job points to this tiler job */ - panfrost_link_job_pair(ctx->u_tiler_jobs[ctx->draw_count - 1], transfer.gpu); - } else { - /* The only vertex job so far points to first tiler job */ - panfrost_link_job_pair(ctx->u_vertex_jobs[0], transfer.gpu); - } - } else { - if (ctx->draw_count) { - /* Previous vertex job points to this vertex job */ - panfrost_link_job_pair(ctx->u_vertex_jobs[ctx->draw_count - 1], transfer.gpu); - - /* Last vertex job points to first tiler job */ - panfrost_link_job_pair(&job, ctx->tiler_jobs[0]); - } else { - /* Have the first vertex job depend on the set value job */ - job.job_dependency_index_1 = ctx->u_set_value_job->job_index; - panfrost_link_job_pair(ctx->u_set_value_job, transfer.gpu); - } - } - memcpy(transfer.cpu, &job, sizeof(job)); memcpy(transfer.cpu + sizeof(job) - offset, payload, sizeof(*payload)); return transfer; } -/* Generates a set value job. It's unclear what exactly this does, why it's - * necessary, and when to call it. */ - -static void -panfrost_set_value_job(struct panfrost_context *ctx) -{ - struct mali_job_descriptor_header job = { - .job_type = JOB_TYPE_SET_VALUE, - .job_descriptor_size = 1, - .job_index = 1, - }; - - struct mali_payload_set_value payload = { - .out = ctx->tiler_polygon_list.gpu, - .unknown = 0x3, - }; - - struct panfrost_transfer transfer = panfrost_allocate_transient(ctx, sizeof(job) + sizeof(payload)); - memcpy(transfer.cpu, &job, sizeof(job)); - memcpy(transfer.cpu + sizeof(job), &payload, sizeof(payload)); - - ctx->u_set_value_job = (struct mali_job_descriptor_header *) transfer.cpu; - ctx->set_value_job = transfer.gpu; -} - static mali_ptr panfrost_emit_varyings( struct panfrost_context *ctx, @@ -681,6 +610,29 @@ panfrost_emit_varying_descriptor( for (unsigned i = 0; i < fs->tripipe->varying_count; i++) { unsigned j; + /* If we have a point sprite replacement, handle that here. We + * have to translate location first. TODO: Flip y in shader. + * We're already keying ... just time crunch .. */ + + unsigned loc = fs->varyings_loc[i]; + unsigned pnt_loc = + (loc >= VARYING_SLOT_VAR0) ? (loc - VARYING_SLOT_VAR0) : + (loc == VARYING_SLOT_PNTC) ? 8 : + ~0; + + if (~pnt_loc && fs->point_sprite_mask & (1 << pnt_loc)) { + /* gl_PointCoord index by convention */ + fs->varyings[i].index = 3; + fs->reads_point_coord = true; + + /* Swizzle out the z/w to 0/1 */ + fs->varyings[i].format = MALI_RG16F; + fs->varyings[i].swizzle = + panfrost_get_default_swizzle(2); + + continue; + } + if (fs->varyings[i].index) continue; @@ -1035,6 +987,69 @@ static void panfrost_upload_sysvals(struct panfrost_context *ctx, void *buf, } } +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, + 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->gpu; + else if (cb->user_buffer) + return panfrost_upload_transient(ctx, cb->user_buffer, 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 +panfrost_ubo_count(struct panfrost_context *ctx, enum pipe_shader_type stage) +{ + unsigned mask = ctx->constant_buffer[stage].enabled_mask | 1; + return 32 - __builtin_clz(mask); +} + +/* Fixes up a shader state with current state, returning a GPU address to the + * patched shader */ + +static mali_ptr +panfrost_patch_shader_state( + struct panfrost_context *ctx, + struct panfrost_shader_state *ss, + enum pipe_shader_type stage) +{ + ss->tripipe->texture_count = ctx->sampler_view_count[stage]; + ss->tripipe->sampler_count = ctx->sampler_count[stage]; + + ss->tripipe->midgard1.flags = 0x220; + + unsigned ubo_count = panfrost_ubo_count(ctx, stage); + ss->tripipe->midgard1.uniform_buffer_count = ubo_count; + + return ss->tripipe_gpu; +} + /* Go through dirty flags and actualise them in the cmdstream. */ void @@ -1056,6 +1071,8 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) SET_BIT(ctx->fragment_shader_core.unknown2_4, MALI_NO_MSAA, !msaa); } + panfrost_job_set_requirements(ctx, job); + if (ctx->occlusion_query) { ctx->payload_tiler.gl_enables |= MALI_OCCLUSION_QUERY | MALI_OCCLUSION_PRECISE; ctx->payload_tiler.postfix.occlusion_counter = ctx->occlusion_query->transfer.gpu; @@ -1066,15 +1083,8 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) struct panfrost_shader_state *vs = &ctx->vs->variants[ctx->vs->active_variant]; - /* Late shader descriptor assignments */ - - vs->tripipe->texture_count = ctx->sampler_view_count[PIPE_SHADER_VERTEX]; - vs->tripipe->sampler_count = ctx->sampler_count[PIPE_SHADER_VERTEX]; - - /* Who knows */ - vs->tripipe->midgard1.unknown1 = 0x2201; - - ctx->payload_vertex.postfix._shader_upper = vs->tripipe_gpu >> 4; + ctx->payload_vertex.postfix._shader_upper = + panfrost_patch_shader_state(ctx, vs, PIPE_SHADER_VERTEX) >> 4; } if (ctx->dirty & (PAN_DIRTY_RASTERIZER | PAN_DIRTY_VS)) { @@ -1096,13 +1106,20 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) assert(ctx->fs); struct panfrost_shader_state *variant = &ctx->fs->variants[ctx->fs->active_variant]; + panfrost_patch_shader_state(ctx, variant, PIPE_SHADER_FRAGMENT); + #define COPY(name) ctx->fragment_shader_core.name = variant->tripipe->name COPY(shader); COPY(attribute_count); COPY(varying_count); + COPY(texture_count); + COPY(sampler_count); + COPY(sampler_count); COPY(midgard1.uniform_count); + COPY(midgard1.uniform_buffer_count); COPY(midgard1.work_count); + COPY(midgard1.flags); COPY(midgard1.unknown2); #undef COPY @@ -1112,8 +1129,13 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) ctx->fragment_shader_core.midgard1.work_count = /*MAX2(ctx->fragment_shader_core.midgard1.work_count, ctx->blend->blend_work_count)*/16; /* Set late due to depending on render state */ - /* The one at the end seems to mean "1 UBO" */ - unsigned flags = MALI_EARLY_Z | 0x200 | 0x2000 | 0x1; + unsigned flags = ctx->fragment_shader_core.midgard1.flags; + + /* Depending on whether it's legal to in the given shader, we + * try to enable early-z testing (or forward-pixel kill?) */ + + if (!variant->can_discard) + flags |= MALI_EARLY_Z; /* Any time texturing is used, derivatives are implicitly * calculated, so we need to enable helper invocations */ @@ -1121,11 +1143,7 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) if (ctx->sampler_view_count[PIPE_SHADER_FRAGMENT]) flags |= MALI_HELPER_INVOCATIONS; - ctx->fragment_shader_core.midgard1.unknown1 = flags; - - /* Assign texture/sample count right before upload */ - ctx->fragment_shader_core.texture_count = ctx->sampler_view_count[PIPE_SHADER_FRAGMENT]; - ctx->fragment_shader_core.sampler_count = ctx->sampler_count[PIPE_SHADER_FRAGMENT]; + ctx->fragment_shader_core.midgard1.flags = flags; /* Assign the stencil refs late */ ctx->fragment_shader_core.stencil_front.ref = ctx->stencil_ref.ref_value[0]; @@ -1140,9 +1158,7 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) if (variant->can_discard) { ctx->fragment_shader_core.unknown2_3 |= MALI_CAN_DISCARD; - ctx->fragment_shader_core.midgard1.unknown1 &= ~MALI_EARLY_Z; - ctx->fragment_shader_core.midgard1.unknown1 |= 0x4000; - ctx->fragment_shader_core.midgard1.unknown1 = 0x4200; + ctx->fragment_shader_core.midgard1.flags |= 0x400; } /* Check if we're using the default blend descriptor (fast path) */ @@ -1213,6 +1229,7 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) for (unsigned i = 0; i < 1; ++i) { bool is_srgb = + (ctx->pipe_framebuffer.nr_cbufs > i) && util_format_is_srgb(ctx->pipe_framebuffer.cbufs[i]->format); rts[i].flags = blend_count; @@ -1258,16 +1275,23 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) struct panfrost_shader_state *fs = &ctx->fs->variants[ctx->fs->active_variant]; struct panfrost_shader_state *ss = (i == PIPE_SHADER_FRAGMENT) ? fs : vs; + /* 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 size = sys_size + buf->size; + 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(ctx, size); /* Upload sysvals requested by the shader */ panfrost_upload_sysvals(ctx, transfer.cpu, ss, i); /* Upload uniforms */ - memcpy(transfer.cpu + sys_size, buf->buffer, buf->size); + if (has_uniforms) { + const void *cpu = panfrost_map_constant_buffer_cpu(buf, 0); + memcpy(transfer.cpu + sys_size, cpu, uniform_size); + } int uniform_count = 0; @@ -1288,20 +1312,50 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) unreachable("Invalid shader stage\n"); } - /* Also attach the same buffer as a UBO for extended access */ + /* Next up, attach UBOs. UBO #0 is the uniforms we just + * uploaded */ - struct mali_uniform_buffer_meta uniform_buffers[] = { - { - .size = MALI_POSITIVE((2 + uniform_count)), - .ptr = transfer.gpu >> 2, - }, - }; + unsigned ubo_count = panfrost_ubo_count(ctx, i); + assert(ubo_count >= 1); + + size_t sz = sizeof(struct mali_uniform_buffer_meta) * ubo_count; + struct mali_uniform_buffer_meta *ubos = calloc(sz, 1); + + /* Upload uniforms as a UBO */ + ubos[0].size = MALI_POSITIVE((2 + uniform_count)); + ubos[0].ptr = transfer.gpu >> 2; + + /* The rest are honest-to-goodness UBOs */ + + for (unsigned ubo = 1; ubo < ubo_count; ++ubo) { + size_t sz = buf->cb[ubo].buffer_size; + + bool enabled = buf->enabled_mask & (1 << ubo); + bool empty = sz == 0; + + if (!enabled || empty) { + /* Stub out disabled UBOs to catch accesses */ + + ubos[ubo].size = 0; + ubos[ubo].ptr = 0xDEAD0000; + continue; + } - mali_ptr ubufs = panfrost_upload_transient(ctx, uniform_buffers, sizeof(uniform_buffers)); + mali_ptr gpu = panfrost_map_constant_buffer_gpu(ctx, buf, ubo); + + unsigned bytes_per_field = 16; + unsigned aligned = ALIGN(sz, bytes_per_field); + unsigned fields = aligned / bytes_per_field; + + ubos[ubo].size = MALI_POSITIVE(fields); + ubos[ubo].ptr = gpu >> 2; + } + + mali_ptr ubufs = panfrost_upload_transient(ctx, ubos, sz); postfix->uniforms = transfer.gpu; postfix->uniform_buffers = ubufs; - buf->dirty = 0; + buf->dirty_mask = 0; } /* TODO: Upload the viewport somewhere more appropriate */ @@ -1372,6 +1426,13 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) miny = MIN2(ctx->pipe_framebuffer.height, miny); maxy = MIN2(ctx->pipe_framebuffer.height, maxy); + /* Update the job, unless we're doing wallpapering (whose lack of + * scissor we can ignore, since if we "miss" a tile of wallpaper, it'll + * just... be faster :) */ + + if (!ctx->wallpaper_batch) + panfrost_job_union_scissor(job, minx, miny, maxx, maxy); + /* Upload */ view.viewport0[0] = minx; @@ -1393,28 +1454,28 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) static void panfrost_queue_draw(struct panfrost_context *ctx) { - /* TODO: Expand the array? */ - if (ctx->draw_count >= MAX_DRAW_CALLS) { - DBG("Job buffer overflow, ignoring draw\n"); - assert(0); - } - /* Handle dirty flags now */ panfrost_emit_for_draw(ctx, true); - /* We need a set_value job before any other draw jobs */ - if (ctx->draw_count == 0) - panfrost_set_value_job(ctx); + /* If rasterizer discard is enable, only submit the vertex */ + + bool rasterizer_discard = ctx->rasterizer + && ctx->rasterizer->base.rasterizer_discard; struct panfrost_transfer vertex = panfrost_vertex_tiler_job(ctx, false); - ctx->u_vertex_jobs[ctx->vertex_job_count] = (struct mali_job_descriptor_header *) vertex.cpu; - ctx->vertex_jobs[ctx->vertex_job_count++] = vertex.gpu; + struct panfrost_transfer tiler; + + if (!rasterizer_discard) + tiler = panfrost_vertex_tiler_job(ctx, true); - struct panfrost_transfer tiler = panfrost_vertex_tiler_job(ctx, true); - ctx->u_tiler_jobs[ctx->tiler_job_count] = (struct mali_job_descriptor_header *) tiler.cpu; - ctx->tiler_jobs[ctx->tiler_job_count++] = tiler.gpu; + struct panfrost_job *batch = panfrost_get_job_for_fbo(ctx); - ctx->draw_count++; + if (rasterizer_discard) + panfrost_scoreboard_queue_vertex_job(batch, vertex, FALSE); + else if (ctx->wallpaper_batch) + panfrost_scoreboard_queue_fused_job_prepend(batch, vertex, tiler); + else + panfrost_scoreboard_queue_fused_job(batch, vertex, tiler); } /* The entire frame is in memory -- send it off to the kernel! */ @@ -1434,25 +1495,14 @@ panfrost_submit_frame(struct panfrost_context *ctx, bool flush_immediate, /* If visual, we can stall a frame */ if (!flush_immediate) - screen->driver->force_flush_fragment(ctx, fence); + panfrost_drm_force_flush_fragment(ctx, fence); screen->last_fragment_flushed = false; screen->last_job = job; /* If readback, flush now (hurts the pipelined performance) */ if (flush_immediate) - screen->driver->force_flush_fragment(ctx, fence); - - if (screen->driver->dump_counters && pan_counters_base) { - screen->driver->dump_counters(screen); - - char filename[128]; - snprintf(filename, sizeof(filename), "%s/frame%d.mdgprf", pan_counters_base, ++performance_counter_number); - FILE *fp = fopen(filename, "wb"); - fwrite(screen->perf_counters.cpu, 4096, sizeof(uint32_t), fp); - fclose(fp); - } - + panfrost_drm_force_flush_fragment(ctx, fence); #endif } @@ -1465,35 +1515,21 @@ panfrost_draw_wallpaper(struct pipe_context *pipe) if (ctx->pipe_framebuffer.cbufs[0] == NULL) return; - /* Blit the wallpaper in */ - panfrost_blit_wallpaper(ctx); + /* Check if the buffer has any content on it worth preserving */ - /* We are flushing all queued draws and we know that no more jobs will - * be added until the next frame. - * We also know that the last jobs are the wallpaper jobs, and they - * need to be linked so they execute right after the set_value job. - */ - - /* set_value job to wallpaper vertex job */ - panfrost_link_job_pair(ctx->u_set_value_job, ctx->vertex_jobs[ctx->vertex_job_count - 1]); - ctx->u_vertex_jobs[ctx->vertex_job_count - 1]->job_dependency_index_1 = ctx->u_set_value_job->job_index; + struct pipe_surface *surf = ctx->pipe_framebuffer.cbufs[0]; + struct panfrost_resource *rsrc = pan_resource(surf->texture); + unsigned level = surf->u.tex.level; - /* wallpaper vertex job to first vertex job */ - panfrost_link_job_pair(ctx->u_vertex_jobs[ctx->vertex_job_count - 1], ctx->vertex_jobs[0]); - ctx->u_vertex_jobs[0]->job_dependency_index_1 = ctx->u_set_value_job->job_index; - - /* last vertex job to wallpaper tiler job */ - panfrost_link_job_pair(ctx->u_vertex_jobs[ctx->vertex_job_count - 2], ctx->tiler_jobs[ctx->tiler_job_count - 1]); - ctx->u_tiler_jobs[ctx->tiler_job_count - 1]->job_dependency_index_1 = ctx->u_vertex_jobs[ctx->vertex_job_count - 1]->job_index; - ctx->u_tiler_jobs[ctx->tiler_job_count - 1]->job_dependency_index_2 = 0; + if (!rsrc->bo->slices[level].initialized) + return; - /* wallpaper tiler job to first tiler job */ - panfrost_link_job_pair(ctx->u_tiler_jobs[ctx->tiler_job_count - 1], ctx->tiler_jobs[0]); - ctx->u_tiler_jobs[0]->job_dependency_index_1 = ctx->u_vertex_jobs[0]->job_index; - ctx->u_tiler_jobs[0]->job_dependency_index_2 = ctx->u_tiler_jobs[ctx->tiler_job_count - 1]->job_index; + /* Save the batch */ + struct panfrost_job *batch = panfrost_get_job_for_fbo(ctx); - /* last tiler job to NULL */ - panfrost_link_job_pair(ctx->u_tiler_jobs[ctx->tiler_job_count - 2], 0); + ctx->wallpaper_batch = batch; + panfrost_blit_wallpaper(ctx); + ctx->wallpaper_batch = NULL; } void @@ -1506,7 +1542,7 @@ panfrost_flush( struct panfrost_job *job = panfrost_get_job_for_fbo(ctx); /* Nothing to do! */ - if (!ctx->draw_count && !job->clear) return; + if (!job->last_job.gpu && !job->clear) return; if (!job->clear) panfrost_draw_wallpaper(&ctx->base); @@ -1751,6 +1787,14 @@ panfrost_bind_rasterizer_state( ctx->rasterizer = hwcso; ctx->dirty |= PAN_DIRTY_RASTERIZER; + + /* Point sprites are emulated */ + + struct panfrost_shader_state *variant = + ctx->fs ? &ctx->fs->variants[ctx->fs->active_variant] : NULL; + + if (ctx->rasterizer->base.sprite_coord_enable || (variant && variant->point_sprite_mask)) + ctx->base.bind_fs_state(&ctx->base, ctx->fs); } static void * @@ -1891,6 +1935,7 @@ panfrost_variant_matches( struct panfrost_shader_state *variant, enum pipe_shader_type type) { + struct pipe_rasterizer_state *rasterizer = &ctx->rasterizer->base; struct pipe_alpha_state *alpha = &ctx->depth_stencil->alpha; bool is_fragment = (type == PIPE_SHADER_FRAGMENT); @@ -1909,6 +1954,22 @@ panfrost_variant_matches( return false; } } + + if (is_fragment && rasterizer && (rasterizer->sprite_coord_enable | + variant->point_sprite_mask)) { + /* Ensure the same varyings are turned to point sprites */ + if (rasterizer->sprite_coord_enable != variant->point_sprite_mask) + return false; + + /* Ensure the orientation is correct */ + bool upper_left = + rasterizer->sprite_coord_mode == + PIPE_SPRITE_COORD_UPPER_LEFT; + + if (variant->point_sprite_upper_left != upper_left) + return false; + } + /* Otherwise, we're good to go */ return true; } @@ -1949,10 +2010,21 @@ panfrost_bind_shader_state( variant = variants->variant_count++; assert(variants->variant_count < MAX_SHADER_VARIANTS); - variants->variants[variant].base = hwcso; + struct panfrost_shader_state *v = + &variants->variants[variant]; - if (type == PIPE_SHADER_FRAGMENT) - variants->variants[variant].alpha_state = ctx->depth_stencil->alpha; + v->base = hwcso; + + if (type == PIPE_SHADER_FRAGMENT) { + v->alpha_state = ctx->depth_stencil->alpha; + + if (ctx->rasterizer) { + v->point_sprite_mask = ctx->rasterizer->base.sprite_coord_enable; + v->point_sprite_upper_left = + ctx->rasterizer->base.sprite_coord_mode == + PIPE_SPRITE_COORD_UPPER_LEFT; + } + } /* Allocate the mapped descriptor ahead-of-time. */ struct panfrost_context *ctx = pan_context(pctx); @@ -2012,43 +2084,18 @@ panfrost_set_constant_buffer( struct panfrost_context *ctx = pan_context(pctx); struct panfrost_constant_buffer *pbuf = &ctx->constant_buffer[shader]; - size_t sz = buf ? buf->buffer_size : 0; - - /* Free previous buffer */ - - pbuf->dirty = true; - pbuf->size = sz; - - if (pbuf->buffer) { - ralloc_free(pbuf->buffer); - pbuf->buffer = NULL; - } - - /* If unbinding, we're done */ - - if (!buf) - return; - - /* Multiple constant buffers not yet supported */ - assert(index == 0); + util_copy_constant_buffer(&pbuf->cb[index], buf); - const uint8_t *cpu; + unsigned mask = (1 << index); - struct panfrost_resource *rsrc = (struct panfrost_resource *) (buf->buffer); - - if (rsrc) { - cpu = rsrc->bo->cpu; - } else if (buf->user_buffer) { - cpu = buf->user_buffer; - } else { - DBG("No constant buffer?\n"); + if (unlikely(!buf)) { + pbuf->enabled_mask &= ~mask; + pbuf->dirty_mask &= ~mask; return; } - /* Copy the constant buffer into the driver context for later upload */ - - pbuf->buffer = rzalloc_size(ctx, sz); - memcpy(pbuf->buffer, cpu + buf->buffer_offset, sz); + pbuf->enabled_mask |= mask; + pbuf->dirty_mask |= mask; } static void @@ -2246,8 +2293,9 @@ panfrost_set_framebuffer_state(struct pipe_context *pctx, * state is being restored by u_blitter */ + struct panfrost_job *job = panfrost_get_job_for_fbo(ctx); bool is_scanout = panfrost_is_scanout(ctx); - bool has_draws = ctx->draw_count > 0; + bool has_draws = job->last_job.gpu; if (!ctx->blitter->running && (!is_scanout || has_draws)) { panfrost_flush(pctx, NULL, PIPE_FLUSH_END_OF_FRAME); @@ -2517,12 +2565,12 @@ panfrost_destroy(struct pipe_context *pipe) if (panfrost->blitter) util_blitter_destroy(panfrost->blitter); - screen->driver->free_slab(screen, &panfrost->scratchpad); - screen->driver->free_slab(screen, &panfrost->varying_mem); - screen->driver->free_slab(screen, &panfrost->shaders); - screen->driver->free_slab(screen, &panfrost->tiler_heap); - screen->driver->free_slab(screen, &panfrost->tiler_polygon_list); - screen->driver->free_slab(screen, &panfrost->tiler_dummy); + panfrost_drm_free_slab(screen, &panfrost->scratchpad); + panfrost_drm_free_slab(screen, &panfrost->varying_mem); + panfrost_drm_free_slab(screen, &panfrost->shaders); + panfrost_drm_free_slab(screen, &panfrost->tiler_heap); + panfrost_drm_free_slab(screen, &panfrost->tiler_polygon_list); + panfrost_drm_free_slab(screen, &panfrost->tiler_dummy); for (int i = 0; i < ARRAY_SIZE(panfrost->transient_pools); ++i) { struct panfrost_memory_entry *entry; @@ -2681,12 +2729,12 @@ panfrost_setup_hardware(struct panfrost_context *ctx) ctx->transient_pools[i].entries[0] = (struct panfrost_memory_entry *) pb_slab_alloc(&screen->slabs, entry_size, HEAP_TRANSIENT); } - screen->driver->allocate_slab(screen, &ctx->scratchpad, 64, false, 0, 0, 0); - screen->driver->allocate_slab(screen, &ctx->varying_mem, 16384, false, PAN_ALLOCATE_INVISIBLE | PAN_ALLOCATE_COHERENT_LOCAL, 0, 0); - screen->driver->allocate_slab(screen, &ctx->shaders, 4096, true, PAN_ALLOCATE_EXECUTE, 0, 0); - screen->driver->allocate_slab(screen, &ctx->tiler_heap, 32768, false, PAN_ALLOCATE_INVISIBLE | PAN_ALLOCATE_GROWABLE, 1, 128); - screen->driver->allocate_slab(screen, &ctx->tiler_polygon_list, 128*128, false, PAN_ALLOCATE_INVISIBLE | PAN_ALLOCATE_GROWABLE, 1, 128); - screen->driver->allocate_slab(screen, &ctx->tiler_dummy, 1, false, PAN_ALLOCATE_INVISIBLE, 0, 0); + panfrost_drm_allocate_slab(screen, &ctx->scratchpad, 64, false, 0, 0, 0); + panfrost_drm_allocate_slab(screen, &ctx->varying_mem, 16384, false, PAN_ALLOCATE_INVISIBLE | PAN_ALLOCATE_COHERENT_LOCAL, 0, 0); + panfrost_drm_allocate_slab(screen, &ctx->shaders, 4096, true, PAN_ALLOCATE_EXECUTE, 0, 0); + panfrost_drm_allocate_slab(screen, &ctx->tiler_heap, 32768, false, PAN_ALLOCATE_INVISIBLE | PAN_ALLOCATE_GROWABLE, 1, 128); + panfrost_drm_allocate_slab(screen, &ctx->tiler_polygon_list, 128*128, false, PAN_ALLOCATE_INVISIBLE | PAN_ALLOCATE_GROWABLE, 1, 128); + panfrost_drm_allocate_slab(screen, &ctx->tiler_dummy, 1, false, PAN_ALLOCATE_INVISIBLE, 0, 0); } /* New context creation, which also does hardware initialisation since I don't @@ -2701,7 +2749,7 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags) struct pipe_context *gallium = (struct pipe_context *) ctx; unsigned gpu_id; - gpu_id = pscreen->driver->query_gpu_version(pscreen); + gpu_id = panfrost_drm_query_gpu_version(pscreen); ctx->is_t6xx = gpu_id <= 0x0750; /* For now, this flag means T760 or less */ ctx->require_sfbd = gpu_id < 0x0750; /* T760 is the first to support MFBD */ @@ -2775,7 +2823,7 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags) panfrost_resource_context_init(gallium); - pscreen->driver->init_context(ctx); + panfrost_drm_init_context(ctx); panfrost_setup_hardware(ctx); @@ -2799,7 +2847,6 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags) panfrost_emit_tiler_payload(ctx); panfrost_invalidate_frame(ctx); panfrost_default_shader_backend(ctx); - panfrost_generate_space_filler_indices(); return gallium; }