diff --git a/src/gallium/drivers/panfrost/pan_blit.c b/src/gallium/drivers/panfrost/pan_blit.c index 3ec8933e37c..2430195cdb1 100644 --- a/src/gallium/drivers/panfrost/pan_blit.c +++ b/src/gallium/drivers/panfrost/pan_blit.c @@ -10,6 +10,77 @@ #include "pan_trace.h" #include "pan_util.h" +static void +panfrost_blitter_draw_rectangle(struct blitter_context *blitter, + void *vertex_elements_cso, + blitter_get_vs_func get_vs, + int x1, int y1, int x2, int y2, + float depth, unsigned num_instances, + enum blitter_attrib_type type, + const struct blitter_attrib *attrib) +{ + assert(num_instances); + + struct pipe_context *ctx = blitter->pipe; + struct panfrost_context *pctx = pan_context(ctx); + struct panfrost_screen *scr = pan_screen(ctx->screen); + + /* Always fallback for now. */ + goto fallback; + + /* Map viewport to the dest rect of the framebuffer. The tiler will then be + * configured to use it as scissor box in order to clip fullscreen + * fragments lying outside. + * + * Note that: tx = x1 + ((x2 - x1) / 2) = (x2 + x1) / 2 + * ty = y1 + ((y2 - y1) / 2) = (y2 + y1) / 2 + */ + const struct pipe_viewport_state viewport_state = { + .scale = { 0.5f * (x2 - x1), 0.5f * (y2 - y1), 1.0f }, + .translate = { 0.5f * (x2 + x1), 0.5f * (y2 + y1), 0.0f }, + .swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X, + .swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y, + .swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z, + .swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W + }; + ctx->set_viewport_states(ctx, 0, 1, &viewport_state); + + /* Map texture coordinates to the fullscreen framebuffer. */ + struct blitter_attrib fs_attrib; + if (type == UTIL_BLITTER_ATTRIB_TEXCOORD_XY || + type == UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW) { + float dfdx = (attrib->texcoord.x2 - attrib->texcoord.x1) / (x2 - x1); + float dfdy = (attrib->texcoord.y2 - attrib->texcoord.y1) / (y2 - y1); + float w = pctx->pipe_framebuffer.width; + float h = pctx->pipe_framebuffer.height; + fs_attrib = *attrib; + fs_attrib.texcoord.x1 -= dfdx * x1; + fs_attrib.texcoord.y1 -= dfdy * y1; + fs_attrib.texcoord.x2 += dfdx * (w - x2); + fs_attrib.texcoord.y2 += dfdy * (h - y2); + }; + + scr->vtbl.draw_fullscreen(pan_context(ctx), get_vs(blitter), type, + &fs_attrib); + return; + + fallback: + /* Fallback to draw_vbo. */ + util_blitter_draw_rectangle(blitter, vertex_elements_cso, get_vs, x1, y1, + x2, y2, depth, num_instances, type, attrib); +} + +struct blitter_context * +panfrost_blitter_create(struct pipe_context *pipe) +{ + struct blitter_context *blitter; + + blitter = util_blitter_create(pipe); + blitter->draw_rectangle = panfrost_blitter_draw_rectangle; + + return blitter; +} + void panfrost_blitter_save(struct panfrost_context *ctx, const enum panfrost_blitter_op blitter_op) diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 58b044c5295..41227ef3fe6 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -3665,6 +3665,43 @@ panfrost_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, } } +static void +panfrost_draw_fullscreen(struct panfrost_context *ctx, + struct panfrost_uncompiled_shader *vs, + enum blitter_attrib_type type, + const struct blitter_attrib *attrib) +{ + assert(!ctx->active_queries); + assert(!ctx->streamout.num_targets); + + PAN_TRACE_FUNC(PAN_TRACE_GL_CMDSTREAM); + + ctx->draw_calls++; + + struct panfrost_batch *batch = prepare_draw(&ctx->base, MESA_PRIM_QUADS); + if (!batch) { + mesa_loge("prepare_draw failed"); + return; + } + + /* Fullscreen draw calls don't configure any position or varying shader but + * link info is needed. The active primitive update takes care of the + * fragment shader variant update. */ + ctx->uncompiled[MESA_SHADER_VERTEX] = vs; + panfrost_update_shader_variant(ctx, MESA_SHADER_VERTEX); + panfrost_update_active_prim(ctx, MESA_PRIM_QUADS); + + /* Clear the dirty vertex flag to ensure the shader state update doesn't + * emit any vertex info. */ + ctx->dirty &= ~PAN_DIRTY_VERTEX; + panfrost_update_state_3d(batch); + panfrost_update_shader_state(batch, MESA_SHADER_FRAGMENT); + panfrost_clean_state_3d(ctx); + + JOBX(launch_draw_fullscreen)(batch, type, attrib); + batch->draw_count++; +} + /* Launch grid is the compute equivalent of draw_vbo, so in this routine, we * construct the COMPUTE job and some of its payload. */ @@ -4683,6 +4720,7 @@ GENX(panfrost_cmdstream_screen_init)(struct panfrost_screen *screen) screen->vtbl.emit_write_timestamp = emit_write_timestamp; screen->vtbl.select_tile_size = GENX(pan_select_tile_size); screen->vtbl.get_conv_desc = get_conv_desc; + screen->vtbl.draw_fullscreen = panfrost_draw_fullscreen; pan_blend_shader_cache_init(&dev->blend_shaders, panfrost_device_gpu_id(dev), dev->kmod.dev->props.gpu_variant, diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index e5dd965cb5a..c6c66d11330 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -1100,7 +1100,7 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags) goto failed; } - ctx->blitter = util_blitter_create(gallium); + ctx->blitter = panfrost_blitter_create(gallium); ctx->writers = _mesa_hash_table_create(gallium, _mesa_hash_pointer, _mesa_key_pointer_equal); diff --git a/src/gallium/drivers/panfrost/pan_csf.c b/src/gallium/drivers/panfrost/pan_csf.c index 35207942b62..48ee647585d 100644 --- a/src/gallium/drivers/panfrost/pan_csf.c +++ b/src/gallium/drivers/panfrost/pan_csf.c @@ -1461,6 +1461,14 @@ GENX(csf_launch_draw_indirect)(struct panfrost_batch *batch, } } +void +GENX(csf_launch_draw_fullscreen)(struct panfrost_batch *batch, + enum blitter_attrib_type type, + const struct blitter_attrib *attrib) +{ + UNREACHABLE("draw fullscreen not implemented for csf"); +} + #define POSITION_FIFO_SIZE (64 * 1024) static enum drm_panthor_group_priority diff --git a/src/gallium/drivers/panfrost/pan_csf.h b/src/gallium/drivers/panfrost/pan_csf.h index b7be8be2339..d649b58dc56 100644 --- a/src/gallium/drivers/panfrost/pan_csf.h +++ b/src/gallium/drivers/panfrost/pan_csf.h @@ -83,6 +83,7 @@ struct panfrost_csf_context { #if defined(PAN_ARCH) && PAN_ARCH >= 10 #include "genxml/gen_macros.h" +#include "util/u_blitter.h" struct panfrost_batch; struct panfrost_context; @@ -120,6 +121,9 @@ void GENX(csf_launch_draw_indirect)(struct panfrost_batch *batch, const struct pipe_draw_info *info, unsigned drawid_offset, const struct pipe_draw_indirect_info *indirect); +void GENX(csf_launch_draw_fullscreen)(struct panfrost_batch *batch, + enum blitter_attrib_type type, + const struct blitter_attrib *attrib); void GENX(csf_emit_write_timestamp)(struct panfrost_batch *batch, struct panfrost_resource *dst, diff --git a/src/gallium/drivers/panfrost/pan_jm.c b/src/gallium/drivers/panfrost/pan_jm.c index 620800d4efb..fdcd060d7af 100644 --- a/src/gallium/drivers/panfrost/pan_jm.c +++ b/src/gallium/drivers/panfrost/pan_jm.c @@ -1020,6 +1020,14 @@ GENX(jm_launch_draw_indirect)(struct panfrost_batch *batch, UNREACHABLE("draw indirect not implemented for jm"); } +void +GENX(jm_launch_draw_fullscreen)(struct panfrost_batch *batch, + enum blitter_attrib_type type, + const struct blitter_attrib *attrib) +{ + UNREACHABLE("draw fullscreen not implemented for jm"); +} + void GENX(jm_emit_write_timestamp)(struct panfrost_batch *batch, struct panfrost_resource *dst, unsigned offset) diff --git a/src/gallium/drivers/panfrost/pan_jm.h b/src/gallium/drivers/panfrost/pan_jm.h index 22ca685d67a..947b2a45acb 100644 --- a/src/gallium/drivers/panfrost/pan_jm.h +++ b/src/gallium/drivers/panfrost/pan_jm.h @@ -26,6 +26,7 @@ struct panfrost_jm_batch { #if defined(PAN_ARCH) && PAN_ARCH < 10 #include "genxml/gen_macros.h" +#include "util/u_blitter.h" struct panfrost_batch; struct panfrost_context; @@ -75,6 +76,9 @@ void GENX(jm_launch_draw_indirect)(struct panfrost_batch *batch, const struct pipe_draw_info *info, unsigned drawid_offset, const struct pipe_draw_indirect_info *indirect); +void GENX(jm_launch_draw_fullscreen)(struct panfrost_batch *batch, + enum blitter_attrib_type type, + const struct blitter_attrib *attrib); void GENX(jm_emit_write_timestamp)(struct panfrost_batch *batch, struct panfrost_resource *dst, diff --git a/src/gallium/drivers/panfrost/pan_resource.h b/src/gallium/drivers/panfrost/pan_resource.h index 5220b5a11d4..95bf4075c24 100644 --- a/src/gallium/drivers/panfrost/pan_resource.h +++ b/src/gallium/drivers/panfrost/pan_resource.h @@ -167,6 +167,8 @@ enum { PAN_RENDER_CLEAR = PAN_SAVE_FRAGMENT_STATE | PAN_SAVE_FRAGMENT_CONSTANT, }; +struct blitter_context *panfrost_blitter_create(struct pipe_context *pipe); + /* Callers should ensure that all AFBC/AFRC resources that will be used in the * blit operation are legalized before calling blitter operations, otherwise * we may trigger a recursive blit */ diff --git a/src/gallium/drivers/panfrost/pan_screen.h b/src/gallium/drivers/panfrost/pan_screen.h index 14eb7ea59fd..29e576256dc 100644 --- a/src/gallium/drivers/panfrost/pan_screen.h +++ b/src/gallium/drivers/panfrost/pan_screen.h @@ -15,6 +15,7 @@ #include "util/disk_cache.h" #include "util/log.h" #include "util/set.h" +#include "util/u_blitter.h" #include "util/u_dynarray.h" #include "pan_device.h" @@ -30,6 +31,7 @@ struct panfrost_batch; struct panfrost_context; struct panfrost_resource; struct panfrost_compiled_shader; +struct panfrost_uncompiled_shader; struct pan_fb_info; struct pan_blend_state; @@ -92,6 +94,12 @@ struct panfrost_vtable { /* construct a render target blend descriptor */ uint64_t (*get_conv_desc)(enum pipe_format fmt, unsigned rt, unsigned force_size, bool dithered); + + /* Run a fullscreen draw call (for blits) */ + void (*draw_fullscreen)(struct panfrost_context *ctx, + struct panfrost_uncompiled_shader *vs, + enum blitter_attrib_type type, + const struct blitter_attrib *attrib); }; struct panfrost_screen {