From 1b49534df2197c59880ee703ff4dd813bc5f5231 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Wed, 18 Mar 2020 19:27:12 -0700 Subject: [PATCH] lima: add support for R and RG formats Unfortunately these are not supported natively for sampling so we have to lower them. Reviewed-by: Erico Nunes Signed-off-by: Vasily Khoruzhick Tested-by: Marge Bot Part-of: --- src/gallium/drivers/lima/ir/pp/codegen.c | 3 + src/gallium/drivers/lima/lima_context.h | 2 + src/gallium/drivers/lima/lima_format.c | 68 +++++++---- src/gallium/drivers/lima/lima_format.h | 1 + src/gallium/drivers/lima/lima_program.c | 110 +++++++++++++++--- src/gallium/drivers/lima/lima_program.h | 4 +- .../lima/standalone/lima_compiler_cmdline.c | 6 +- 7 files changed, 157 insertions(+), 37 deletions(-) diff --git a/src/gallium/drivers/lima/ir/pp/codegen.c b/src/gallium/drivers/lima/ir/pp/codegen.c index 919bb334147..892b124322b 100644 --- a/src/gallium/drivers/lima/ir/pp/codegen.c +++ b/src/gallium/drivers/lima/ir/pp/codegen.c @@ -814,6 +814,9 @@ bool ppir_codegen_prog(ppir_compiler *comp) } } + if (comp->prog->shader) + ralloc_free(comp->prog->shader); + comp->prog->shader = prog; comp->prog->shader_size = size * sizeof(uint32_t); diff --git a/src/gallium/drivers/lima/lima_context.h b/src/gallium/drivers/lima/lima_context.h index e28617ee7a7..5cda47287c2 100644 --- a/src/gallium/drivers/lima/lima_context.h +++ b/src/gallium/drivers/lima/lima_context.h @@ -44,9 +44,11 @@ struct lima_depth_stencil_alpha_state { }; struct lima_fs_shader_state { + struct pipe_shader_state base; void *shader; int shader_size; int stack_size; + uint8_t swizzles[PIPE_MAX_SAMPLERS][4]; bool uses_discard; struct lima_bo *bo; }; diff --git a/src/gallium/drivers/lima/lima_format.c b/src/gallium/drivers/lima/lima_format.c index fad0f8976ef..872134e79ad 100644 --- a/src/gallium/drivers/lima/lima_format.c +++ b/src/gallium/drivers/lima/lima_format.c @@ -26,6 +26,7 @@ #include #include +#include "util/format/u_format.h" #include #include "lima_format.h" @@ -52,6 +53,8 @@ #define LIMA_PIXEL_FORMAT_B5G5R5A1 0x01 #define LIMA_PIXEL_FORMAT_B4G4R4A4 0x02 #define LIMA_PIXEL_FORMAT_B8G8R8A8 0x03 +#define LIMA_PIXEL_FORMAT_B8 0x04 +#define LIMA_PIXEL_FORMAT_G8B8 0x05 #define LIMA_PIXEL_FORMAT_Z16 0x0e #define LIMA_PIXEL_FORMAT_Z24S8 0x0f @@ -59,13 +62,23 @@ struct lima_format { bool present; int format; bool swap_r_b; - uint32_t channel_layout; + union { + uint32_t channel_layout; + uint8_t swizzle[4]; + }; }; -#define LIMA_TEXEL_FORMAT(pipe, tex, swap) \ +#define SWIZ(x,y,z,w) { \ + PIPE_SWIZZLE_##x, \ + PIPE_SWIZZLE_##y, \ + PIPE_SWIZZLE_##z, \ + PIPE_SWIZZLE_##w \ +} + +#define LIMA_TEXEL_FORMAT(pipe, tex, swap, swiz) \ [PIPE_FORMAT_##pipe] = { \ .present = true, .format = LIMA_TEXEL_FORMAT_##tex, \ - .swap_r_b = swap \ + .swap_r_b = swap, .swizzle = swiz \ } #define LIMA_PIXEL_FORMAT(pipe, pix, swap, ch_layout) \ @@ -75,25 +88,27 @@ struct lima_format { } static const struct lima_format lima_texel_formats[] = { - LIMA_TEXEL_FORMAT(R8G8B8A8_UNORM, RGBA_8888, true), - LIMA_TEXEL_FORMAT(B8G8R8A8_UNORM, RGBA_8888, false), - LIMA_TEXEL_FORMAT(R8G8B8A8_SRGB, RGBA_8888, true), - LIMA_TEXEL_FORMAT(B8G8R8A8_SRGB, RGBA_8888, false), - LIMA_TEXEL_FORMAT(R8G8B8X8_UNORM, RGBX_8888, true), - LIMA_TEXEL_FORMAT(B8G8R8X8_UNORM, RGBX_8888, false), - LIMA_TEXEL_FORMAT(B5G6R5_UNORM, BGR_565, false), - LIMA_TEXEL_FORMAT(B5G5R5A1_UNORM, BGRA_5551, false), - LIMA_TEXEL_FORMAT(B4G4R4A4_UNORM, BGRA_4444, false), - LIMA_TEXEL_FORMAT(Z24_UNORM_S8_UINT, Z24X8, false), - LIMA_TEXEL_FORMAT(Z24X8_UNORM, Z24X8, false), - LIMA_TEXEL_FORMAT(L16_UNORM, L16, false), - LIMA_TEXEL_FORMAT(L8_UNORM, L8, false), - LIMA_TEXEL_FORMAT(A16_UNORM, A16, false), - LIMA_TEXEL_FORMAT(A8_UNORM, A8, false), - LIMA_TEXEL_FORMAT(I16_UNORM, I16, false), - LIMA_TEXEL_FORMAT(I8_UNORM, I8, false), - LIMA_TEXEL_FORMAT(L8A8_UNORM, L8A8, false), - LIMA_TEXEL_FORMAT(ETC1_RGB8, ETC1_RGB8, false), + LIMA_TEXEL_FORMAT(R8G8B8A8_UNORM, RGBA_8888, true, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(B8G8R8A8_UNORM, RGBA_8888, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(R8G8B8A8_SRGB, RGBA_8888, true, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(B8G8R8A8_SRGB, RGBA_8888, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(R8G8B8X8_UNORM, RGBX_8888, true, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(B8G8R8X8_UNORM, RGBX_8888, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(B5G6R5_UNORM, BGR_565, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(B5G5R5A1_UNORM, BGRA_5551, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(B4G4R4A4_UNORM, BGRA_4444, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(Z24_UNORM_S8_UINT, Z24X8, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(Z24X8_UNORM, Z24X8, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(L16_UNORM, L16, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(L8_UNORM, L8, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(A16_UNORM, A16, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(A8_UNORM, A8, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(I16_UNORM, I16, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(I8_UNORM, I8, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(L8A8_UNORM, L8A8, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(ETC1_RGB8, ETC1_RGB8, false, SWIZ(X, Y, Z, W)), + LIMA_TEXEL_FORMAT(R8_UNORM, L8, false, SWIZ(X, 0, 0, 1)), + LIMA_TEXEL_FORMAT(R8G8_UNORM, L8A8, false, SWIZ(X, W, 0, 1)), }; static const struct lima_format lima_pixel_formats[] = { @@ -106,6 +121,9 @@ static const struct lima_format lima_pixel_formats[] = { LIMA_PIXEL_FORMAT(B5G6R5_UNORM, B5G6R5, false, 0x8565), LIMA_PIXEL_FORMAT(B5G5R5A1_UNORM, B5G5R5A1, false, 0x8565), LIMA_PIXEL_FORMAT(B4G4R4A4_UNORM, B4G4R4A4, false, 0x8444), + /* FIXME: reload doesn't work for these formats for some reason */ + //LIMA_PIXEL_FORMAT(R8_UNORM, B8, true, 0x8888), + //LIMA_PIXEL_FORMAT(R8G8_UNORM, G8B8, true, 0x8888), LIMA_PIXEL_FORMAT(Z24_UNORM_S8_UINT, Z24S8, false, 0x0000), LIMA_PIXEL_FORMAT(Z24X8_UNORM, Z24S8, false, 0x0000), }; @@ -188,6 +206,12 @@ lima_format_get_pixel_swap_rb(enum pipe_format f) return lima_pixel_formats[f].swap_r_b; } +const uint8_t * +lima_format_get_texel_swizzle(enum pipe_format f) +{ + return lima_texel_formats[f].swizzle; +} + uint32_t lima_format_get_channel_layout(enum pipe_format f) { diff --git a/src/gallium/drivers/lima/lima_format.h b/src/gallium/drivers/lima/lima_format.h index 856f8ba5acb..fb472641d6e 100644 --- a/src/gallium/drivers/lima/lima_format.h +++ b/src/gallium/drivers/lima/lima_format.h @@ -35,6 +35,7 @@ int lima_format_get_pixel(enum pipe_format f); int lima_format_get_texel_reload(enum pipe_format f); bool lima_format_get_texel_swap_rb(enum pipe_format f); bool lima_format_get_pixel_swap_rb(enum pipe_format f); +const uint8_t *lima_format_get_texel_swizzle(enum pipe_format f); uint32_t lima_format_get_channel_layout(enum pipe_format f); #endif diff --git a/src/gallium/drivers/lima/lima_program.c b/src/gallium/drivers/lima/lima_program.c index 33a695557a6..19eef27f320 100644 --- a/src/gallium/drivers/lima/lima_program.c +++ b/src/gallium/drivers/lima/lima_program.c @@ -37,6 +37,8 @@ #include "lima_job.h" #include "lima_program.h" #include "lima_bo.h" +#include "lima_format.h" + #include "ir/lima_ir.h" static const nir_shader_compiler_options vs_nir_options = { @@ -73,10 +75,6 @@ static const nir_shader_compiler_options fs_nir_options = { .lower_vector_cmp = true, }; -static const struct nir_lower_tex_options tex_options = { - .lower_txp = ~0u, -}; - const void * lima_program_get_compiler_options(enum pipe_shader_type shader) { @@ -189,14 +187,15 @@ lima_alu_to_scalar_filter_cb(const nir_instr *instr, const void *data) } void -lima_program_optimize_fs_nir(struct nir_shader *s) +lima_program_optimize_fs_nir(struct nir_shader *s, + struct nir_lower_tex_options *tex_options) { bool progress; NIR_PASS_V(s, nir_lower_fragcoord_wtrans); NIR_PASS_V(s, nir_lower_io, nir_var_all, type_size, 0); NIR_PASS_V(s, nir_lower_regs_to_ssa); - NIR_PASS_V(s, nir_lower_tex, &tex_options); + NIR_PASS_V(s, nir_lower_tex, tex_options); do { progress = false; @@ -252,12 +251,35 @@ lima_program_optimize_fs_nir(struct nir_shader *s) nir_sweep(s); } +static bool +lima_fs_compile_shader(struct lima_context *ctx, + struct lima_fs_shader_state *fs, + struct nir_lower_tex_options *tex_options) +{ + struct lima_screen *screen = lima_screen(ctx->base.screen); + nir_shader *nir = nir_shader_clone(fs, fs->base.ir.nir); + + lima_program_optimize_fs_nir(nir, tex_options); + + if (lima_debug & LIMA_DEBUG_PP) + nir_print_shader(nir, stdout); + + if (!ppir_compile_nir(fs, nir, screen->pp_ra, &ctx->debug)) { + ralloc_free(nir); + return false; + } + + fs->uses_discard = nir->info.fs.uses_discard; + ralloc_free(nir); + + return true; +} + static void * lima_create_fs_state(struct pipe_context *pctx, const struct pipe_shader_state *cso) { struct lima_context *ctx = lima_context(pctx); - struct lima_screen *screen = lima_screen(pctx->screen); struct lima_fs_shader_state *so = rzalloc(NULL, struct lima_fs_shader_state); if (!so) @@ -265,6 +287,9 @@ lima_create_fs_state(struct pipe_context *pctx, nir_shader *nir; if (cso->type == PIPE_SHADER_IR_NIR) + /* The backend takes ownership of the NIR shader on state + * creation. + */ nir = cso->ir.nir; else { assert(cso->type == PIPE_SHADER_IR_TGSI); @@ -272,18 +297,28 @@ lima_create_fs_state(struct pipe_context *pctx, nir = tgsi_to_nir(cso->tokens, pctx->screen); } - lima_program_optimize_fs_nir(nir); + so->base.type = PIPE_SHADER_IR_NIR; + so->base.ir.nir = nir; - if (lima_debug & LIMA_DEBUG_PP) - nir_print_shader(nir, stdout); + uint8_t identity[4] = { PIPE_SWIZZLE_X, + PIPE_SWIZZLE_Y, + PIPE_SWIZZLE_Z, + PIPE_SWIZZLE_W }; + + struct nir_lower_tex_options tex_options = { + .lower_txp = ~0u, + .swizzle_result = 0, + }; - if (!ppir_compile_nir(so, nir, screen->pp_ra, &ctx->debug)) { + /* Initialize with identity swizzles. That should suffice for most shaders */ + for (int i = 0; i < PIPE_MAX_SAMPLERS; i++) + memcpy(so->swizzles[i], identity, 4); + + if (!lima_fs_compile_shader(ctx, so, &tex_options)) { ralloc_free(so); return NULL; } - so->uses_discard = nir->info.fs.uses_discard; - return so; } @@ -304,6 +339,7 @@ lima_delete_fs_state(struct pipe_context *pctx, void *hwcso) if (so->bo) lima_bo_unreference(so->bo); + ralloc_free(so->base.ir.nir); ralloc_free(so); } @@ -331,6 +367,54 @@ bool lima_update_fs_state(struct lima_context *ctx) { struct lima_fs_shader_state *fs = ctx->fs; + struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj; + struct nir_lower_tex_options tex_options = { + .lower_txp = ~0u, + .swizzle_result = 0, + }; + bool needs_recompile = false; + + /* Check if texture formats has changed since last compilation. + * If it has we need to recompile shader. + */ + if (((ctx->dirty & LIMA_CONTEXT_DIRTY_TEXTURES) && + lima_tex->num_samplers && + lima_tex->num_textures)) { + uint8_t identity[4] = { PIPE_SWIZZLE_X, + PIPE_SWIZZLE_Y, + PIPE_SWIZZLE_Z, + PIPE_SWIZZLE_W }; + for (int i = 0; i < lima_tex->num_samplers; i++) { + struct lima_sampler_view *texture = lima_sampler_view(lima_tex->textures[i]); + struct pipe_resource *prsc = texture->base.texture; + const uint8_t *swizzle = lima_format_get_texel_swizzle(prsc->format); + if (memcmp(fs->swizzles[i], swizzle, 4)) { + needs_recompile = true; + memcpy(fs->swizzles[i], swizzle, 4); + } + + for (int j = 0; j < 4; j++) + tex_options.swizzles[i][j] = swizzle[j]; + + if (memcmp(swizzle, identity, 4)) + tex_options.swizzle_result |= (1 << i); + } + + /* Fill rest with identity swizzle */ + for (int i = lima_tex->num_samplers; i < PIPE_MAX_SAMPLERS; i++) + memcpy(fs->swizzles[i], identity, 4); + } + + if (needs_recompile) { + if (fs->bo) { + lima_bo_unreference(fs->bo); + fs->bo = NULL; + } + + if (!lima_fs_compile_shader(ctx, fs, &tex_options)) + return false; + } + if (!fs->bo) { struct lima_screen *screen = lima_screen(ctx->base.screen); fs->bo = lima_bo_create(screen, fs->shader_size, 0); diff --git a/src/gallium/drivers/lima/lima_program.h b/src/gallium/drivers/lima/lima_program.h index acbc18dc033..2eb156912f0 100644 --- a/src/gallium/drivers/lima/lima_program.h +++ b/src/gallium/drivers/lima/lima_program.h @@ -35,6 +35,8 @@ struct nir_shader; void lima_program_optimize_vs_nir(struct nir_shader *s); -void lima_program_optimize_fs_nir(struct nir_shader *s); +struct nir_lower_tex_options; +void lima_program_optimize_fs_nir(struct nir_shader *s, + struct nir_lower_tex_options *tex_options); #endif diff --git a/src/gallium/drivers/lima/standalone/lima_compiler_cmdline.c b/src/gallium/drivers/lima/standalone/lima_compiler_cmdline.c index e43dc2dc303..a05caf6e306 100644 --- a/src/gallium/drivers/lima/standalone/lima_compiler_cmdline.c +++ b/src/gallium/drivers/lima/standalone/lima_compiler_cmdline.c @@ -212,6 +212,10 @@ main(int argc, char **argv) return -1; } + struct nir_lower_tex_options tex_options = { + .lower_txp = ~0u, + }; + nir_shader *nir = load_glsl(1, filename, stage); switch (stage) { @@ -224,7 +228,7 @@ main(int argc, char **argv) gpir_compile_nir(vs, nir, NULL); break; case MESA_SHADER_FRAGMENT: - lima_program_optimize_fs_nir(nir); + lima_program_optimize_fs_nir(nir, &tex_options); nir_print_shader(nir, stdout); -- 2.30.2