X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fetnaviv%2Fetnaviv_shader.c;h=d2d736bdee5d9d058b582d2c99359d2a5db82e99;hb=0bf667984b074105be62116fa76be42b2a422e28;hp=5035eaffde6e7750599a21e49b234b2773fe67a1;hpb=9da54fdcb5b591a7d6c96871e92f8b183c0a5130;p=mesa.git diff --git a/src/gallium/drivers/etnaviv/etnaviv_shader.c b/src/gallium/drivers/etnaviv/etnaviv_shader.c index 5035eaffde6..d2d736bdee5 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_shader.c +++ b/src/gallium/drivers/etnaviv/etnaviv_shader.c @@ -29,12 +29,30 @@ #include "etnaviv_compiler.h" #include "etnaviv_context.h" #include "etnaviv_debug.h" +#include "etnaviv_screen.h" #include "etnaviv_util.h" #include "tgsi/tgsi_parse.h" #include "util/u_math.h" #include "util/u_memory.h" +/* Upload shader code to bo, if not already done */ +static bool etna_icache_upload_shader(struct etna_context *ctx, struct etna_shader_variant *v) +{ + if (v->bo) + return true; + v->bo = etna_bo_new(ctx->screen->dev, v->code_size*4, DRM_ETNA_GEM_CACHE_WC); + if (!v->bo) + return false; + + void *buf = etna_bo_map(v->bo); + etna_bo_cpu_prep(v->bo, DRM_ETNA_PREP_WRITE); + memcpy(buf, v->code, v->code_size*4); + etna_bo_cpu_fini(v->bo); + DBG("Uploaded %s of %u words to bo %p", v->processor == PIPE_SHADER_FRAGMENT ? "fs":"vs", v->code_size, v->bo); + return true; +} + /* Link vs and fs together: fill in shader_state from vs and fs * as this function is called every time a new fs or vs is bound, the goal is to * do little processing as possible here, and to precompute as much as possible in @@ -45,7 +63,7 @@ */ static bool etna_link_shaders(struct etna_context *ctx, struct compiled_shader_state *cs, - const struct etna_shader_variant *vs, const struct etna_shader_variant *fs) + struct etna_shader_variant *vs, struct etna_shader_variant *fs) { struct etna_shader_link_info link = { }; @@ -161,12 +179,43 @@ etna_link_shaders(struct etna_context *ctx, struct compiled_shader_state *cs, cs->GL_VARYING_COMPONENT_USE[0] = component_use[0]; cs->GL_VARYING_COMPONENT_USE[1] = component_use[1]; + cs->GL_HALTI5_SH_SPECIALS = + 0x7f7f0000 | /* unknown bits, probably other PS inputs */ + /* pointsize is last (see above) */ + VIVS_GL_HALTI5_SH_SPECIALS_VS_PSIZE_OUT((vs->vs_pointsize_out_reg != -1) ? + cs->VS_OUTPUT_COUNT * 4 : 0x00) | + VIVS_GL_HALTI5_SH_SPECIALS_PS_PCOORD_IN((link.pcoord_varying_comp_ofs != -1) ? + link.pcoord_varying_comp_ofs : 0x7f); + /* reference instruction memory */ cs->vs_inst_mem_size = vs->code_size; cs->VS_INST_MEM = vs->code; + cs->ps_inst_mem_size = fs->code_size; cs->PS_INST_MEM = fs->code; + if (vs->needs_icache | fs->needs_icache) { + /* If either of the shaders needs ICACHE, we use it for both. It is + * either switched on or off for the entire shader processor. + */ + if (!etna_icache_upload_shader(ctx, vs) || + !etna_icache_upload_shader(ctx, fs)) { + assert(0); + return false; + } + + cs->VS_INST_ADDR.bo = vs->bo; + cs->VS_INST_ADDR.offset = 0; + cs->VS_INST_ADDR.flags = ETNA_RELOC_READ; + cs->PS_INST_ADDR.bo = fs->bo; + cs->PS_INST_ADDR.offset = 0; + cs->PS_INST_ADDR.flags = ETNA_RELOC_READ; + } else { + /* clear relocs */ + memset(&cs->VS_INST_ADDR, 0, sizeof(cs->VS_INST_ADDR)); + memset(&cs->PS_INST_ADDR, 0, sizeof(cs->PS_INST_ADDR)); + } + return true; } @@ -181,8 +230,7 @@ etna_shader_link(struct etna_context *ctx) } static bool -etna_shader_update_vs_inputs(struct etna_context *ctx, - struct compiled_shader_state *cs, +etna_shader_update_vs_inputs(struct compiled_shader_state *cs, const struct etna_shader_variant *vs, const struct compiled_vertex_elements_state *ves) { @@ -197,7 +245,7 @@ etna_shader_update_vs_inputs(struct etna_context *ctx, num_vs_inputs = MAX2(ves->num_elements, vs->infile.num_reg); if (num_vs_inputs != ves->num_elements) { BUG("Number of elements %u does not match the number of VS inputs %zu", - ctx->vertex_elements->num_elements, ctx->shader.vs->infile.num_reg); + ves->num_elements, vs->infile.num_reg); return false; } @@ -238,37 +286,37 @@ etna_shader_stage(struct etna_shader_variant *shader) } static void -dump_shader_info(struct etna_shader_variant *shader, struct pipe_debug_callback *debug) +dump_shader_info(struct etna_shader_variant *v, struct pipe_debug_callback *debug) { if (!unlikely(etna_mesa_debug & ETNA_DBG_SHADERDB)) return; pipe_debug_message(debug, SHADER_INFO, "\n" - "SHADER-DB: %s prog %d: %u instructions %u temps\n" - "SHADER-DB: %s prog %d: %u immediates %u consts\n" - "SHADER-DB: %s prog %d: %u loops\n", - etna_shader_stage(shader), - shader->id, - shader->code_size, - shader->num_temps, - etna_shader_stage(shader), - shader->id, - shader->uniforms.imm_count, - shader->uniforms.const_count, - etna_shader_stage(shader), - shader->id, - shader->num_loops); + "SHADER-DB: %s prog %d/%d: %u instructions %u temps\n" + "SHADER-DB: %s prog %d/%d: %u immediates %u consts\n" + "SHADER-DB: %s prog %d/%d: %u loops\n", + etna_shader_stage(v), + v->shader->id, v->id, + v->code_size, + v->num_temps, + etna_shader_stage(v), + v->shader->id, v->id, + v->uniforms.imm_count, + v->uniforms.const_count, + etna_shader_stage(v), + v->shader->id, v->id, + v->num_loops); } bool etna_shader_update_vertex(struct etna_context *ctx) { - return etna_shader_update_vs_inputs(ctx, &ctx->shader_state, ctx->shader.vs, + return etna_shader_update_vs_inputs(&ctx->shader_state, ctx->shader.vs, ctx->vertex_elements); } static struct etna_shader_variant * -create_variant(struct etna_shader *shader) +create_variant(struct etna_shader *shader, struct etna_shader_key key) { struct etna_shader_variant *v = CALLOC_STRUCT(etna_shader_variant); int ret; @@ -277,6 +325,7 @@ create_variant(struct etna_shader *shader) return NULL; v->shader = shader; + v->key = key; ret = etna_compile_shader(v); if (!ret) { @@ -293,6 +342,27 @@ fail: return NULL; } +struct etna_shader_variant * +etna_shader_variant(struct etna_shader *shader, struct etna_shader_key key, + struct pipe_debug_callback *debug) +{ + struct etna_shader_variant *v; + + for (v = shader->variants; v; v = v->next) + if (etna_shader_key_equal(&key, &v->key)) + return v; + + /* compile new variant if it doesn't exist already */ + v = create_variant(shader, key); + if (v) { + v->next = shader->variants; + shader->variants = v; + dump_shader_info(v, debug); + } + + return v; +} + static void * etna_create_shader_state(struct pipe_context *pctx, const struct pipe_shader_state *pss) @@ -308,17 +378,16 @@ etna_create_shader_state(struct pipe_context *pctx, shader->specs = &ctx->specs; shader->tokens = tgsi_dup_tokens(pss->tokens); - /* compile new variant */ - struct etna_shader_variant *v; - - v = create_variant(shader); - if (v) { - v->next = shader->variants; - shader->variants = v; - dump_shader_info(v, &ctx->debug); + if (etna_mesa_debug & ETNA_DBG_SHADERDB) { + /* if shader-db run, create a standard variant immediately + * (as otherwise nothing will trigger the shader to be + * actually compiled). + */ + struct etna_shader_key key = {}; + etna_shader_variant(shader, key, &ctx->debug); } - return v; + return shader; } static void @@ -331,6 +400,8 @@ etna_delete_shader_state(struct pipe_context *pctx, void *ss) while (v) { t = v; v = v->next; + if (t->bo) + etna_bo_del(t->bo); etna_destroy_shader(t); } @@ -339,30 +410,20 @@ etna_delete_shader_state(struct pipe_context *pctx, void *ss) } static void -etna_bind_fs_state(struct pipe_context *pctx, void *fss_) +etna_bind_fs_state(struct pipe_context *pctx, void *hwcso) { struct etna_context *ctx = etna_context(pctx); - struct etna_shader_variant *fss = fss_; - if (ctx->shader.fs == fss) /* skip if already bound */ - return; - - assert(fss == NULL || fss->processor == PIPE_SHADER_FRAGMENT); - ctx->shader.fs = fss; + ctx->shader.bind_fs = hwcso; ctx->dirty |= ETNA_DIRTY_SHADER; } static void -etna_bind_vs_state(struct pipe_context *pctx, void *vss_) +etna_bind_vs_state(struct pipe_context *pctx, void *hwcso) { struct etna_context *ctx = etna_context(pctx); - struct etna_shader_variant *vss = vss_; - - if (ctx->shader.vs == vss) /* skip if already bound */ - return; - assert(vss == NULL || vss->processor == PIPE_SHADER_VERTEX); - ctx->shader.vs = vss; + ctx->shader.bind_vs = hwcso; ctx->dirty |= ETNA_DIRTY_SHADER; }