X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_wm.c;h=b590b177ece0a60cce123eb95b37374ba4a30c72;hb=5c0436dbf87fef76ba67456f215d9285c38f1816;hp=7eccbcb07e18eb0f1bf8dd42bce5afb0f30da097;hpb=2b7bbd89e87c4025cfc5513a078b1e7a10640357;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c index 7eccbcb07e1..b590b177ece 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -36,11 +36,12 @@ #include "main/formats.h" #include "main/fbobject.h" #include "main/samplerobj.h" +#include "main/framebuffer.h" #include "program/prog_parameter.h" #include "program/program.h" #include "intel_mipmap_tree.h" -#include "glsl/ralloc.h" +#include "util/ralloc.h" /** * Return a bitfield where bit n is set if barycentric interpolation mode n @@ -116,46 +117,58 @@ brw_compute_barycentric_interp_modes(struct brw_context *brw, return barycentric_interp_modes; } +static uint8_t +computed_depth_mode(struct gl_fragment_program *fp) +{ + if (fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { + switch (fp->FragDepthLayout) { + case FRAG_DEPTH_LAYOUT_NONE: + case FRAG_DEPTH_LAYOUT_ANY: + return BRW_PSCDEPTH_ON; + case FRAG_DEPTH_LAYOUT_GREATER: + return BRW_PSCDEPTH_ON_GE; + case FRAG_DEPTH_LAYOUT_LESS: + return BRW_PSCDEPTH_ON_LE; + case FRAG_DEPTH_LAYOUT_UNCHANGED: + return BRW_PSCDEPTH_OFF; + } + } + return BRW_PSCDEPTH_OFF; +} + bool brw_wm_prog_data_compare(const void *in_a, const void *in_b) { const struct brw_wm_prog_data *a = in_a; const struct brw_wm_prog_data *b = in_b; - /* Compare all the struct (including the base) up to the pointers. */ - if (memcmp(a, b, offsetof(struct brw_wm_prog_data, param))) - return false; - - if (memcmp(a->param, b->param, a->nr_params * sizeof(void *))) + /* Compare the base structure. */ + if (!brw_stage_prog_data_compare(&a->base, &b->base)) return false; - if (memcmp(a->pull_param, b->pull_param, a->nr_pull_params * sizeof(void *))) + /* Compare the rest of the structure. */ + const unsigned offset = sizeof(struct brw_stage_prog_data); + if (memcmp(((char *) a) + offset, ((char *) b) + offset, + sizeof(struct brw_wm_prog_data) - offset)) return false; return true; } -void -brw_wm_prog_data_free(const void *in_prog_data) -{ - const struct brw_wm_prog_data *prog_data = in_prog_data; - - ralloc_free((void *)prog_data->param); - ralloc_free((void *)prog_data->pull_param); -} - /** * All Mesa program -> GPU code generation goes through this function. * Depending on the instructions used (i.e. flow control instructions) * we'll use one of two code generators. */ -bool do_wm_prog(struct brw_context *brw, - struct gl_shader_program *prog, - struct brw_fragment_program *fp, - struct brw_wm_prog_key *key) +bool +brw_codegen_wm_prog(struct brw_context *brw, + struct gl_shader_program *prog, + struct brw_fragment_program *fp, + struct brw_wm_prog_key *key) { struct gl_context *ctx = &brw->ctx; - struct brw_wm_compile *c; + void *mem_ctx = ralloc_context(NULL); + struct brw_wm_prog_data prog_data; const GLuint *program; struct gl_shader *fs = NULL; GLuint program_size; @@ -163,7 +176,18 @@ bool do_wm_prog(struct brw_context *brw, if (prog) fs = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; - c = rzalloc(NULL, struct brw_wm_compile); + memset(&prog_data, 0, sizeof(prog_data)); + /* key->alpha_test_func means simulating alpha testing via discards, + * so the shader definitely kills pixels. + */ + prog_data.uses_kill = fp->program.UsesKill || key->alpha_test_func; + prog_data.uses_omask = + fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK); + prog_data.computed_depth_mode = computed_depth_mode(&fp->program); + + /* Use ALT floating point mode for ARB programs so that 0^0 == 1. */ + if (!prog) + prog_data.base.use_alt_mode = true; /* Allocate the references to the uniforms that will end up in the * prog_data associated with the compiled program, and which will be freed @@ -177,42 +201,39 @@ bool do_wm_prog(struct brw_context *brw, } /* The backend also sometimes adds params for texture size. */ param_count += 2 * ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits; - c->prog_data.param = rzalloc_array(NULL, const float *, param_count); - c->prog_data.pull_param = rzalloc_array(NULL, const float *, param_count); - - memcpy(&c->key, key, sizeof(*key)); - - c->prog_data.barycentric_interp_modes = - brw_compute_barycentric_interp_modes(brw, c->key.flat_shade, - c->key.persample_shading, + prog_data.base.param = + rzalloc_array(NULL, const gl_constant_value *, param_count); + prog_data.base.pull_param = + rzalloc_array(NULL, const gl_constant_value *, param_count); + prog_data.base.nr_params = param_count; + + prog_data.barycentric_interp_modes = + brw_compute_barycentric_interp_modes(brw, key->flat_shade, + key->persample_shading, &fp->program); - program = brw_wm_fs_emit(brw, c, &fp->program, prog, &program_size); - if (program == NULL) + program = brw_wm_fs_emit(brw, mem_ctx, key, &prog_data, + &fp->program, prog, &program_size); + if (program == NULL) { + ralloc_free(mem_ctx); return false; + } - /* Scratch space is used for register spilling */ - if (c->last_scratch) { - perf_debug("Fragment shader triggered register spilling. " - "Try reducing the number of live scalar values to " - "improve performance.\n"); - - c->prog_data.total_scratch = brw_get_scratch_size(c->last_scratch); - + if (prog_data.base.total_scratch) { brw_get_scratch_bo(brw, &brw->wm.base.scratch_bo, - c->prog_data.total_scratch * brw->max_wm_threads); + prog_data.base.total_scratch * brw->max_wm_threads); } if (unlikely(INTEL_DEBUG & DEBUG_WM)) fprintf(stderr, "\n"); - brw_upload_cache(&brw->cache, BRW_WM_PROG, - &c->key, sizeof(c->key), + brw_upload_cache(&brw->cache, BRW_CACHE_FS_PROG, + key, sizeof(struct brw_wm_prog_key), program, program_size, - &c->prog_data, sizeof(c->prog_data), + &prog_data, sizeof(prog_data), &brw->wm.base.prog_offset, &brw->wm.prog_data); - ralloc_free(c); + ralloc_free(mem_ctx); return true; } @@ -245,12 +266,16 @@ brw_debug_recompile_sampler_key(struct brw_context *brw, old_key->gl_clamp_mask[1], key->gl_clamp_mask[1]); found |= key_debug(brw, "GL_CLAMP enabled on any texture unit's 3rd coordinate", old_key->gl_clamp_mask[2], key->gl_clamp_mask[2]); - found |= key_debug(brw, "GL_MESA_ycbcr texturing\n", - old_key->yuvtex_mask, key->yuvtex_mask); - found |= key_debug(brw, "GL_MESA_ycbcr UV swapping\n", - old_key->yuvtex_swap_mask, key->yuvtex_swap_mask); found |= key_debug(brw, "gather channel quirk on any texture unit", old_key->gather_channel_quirk_mask, key->gather_channel_quirk_mask); + found |= key_debug(brw, "compressed multisample layout", + old_key->compressed_multisample_layout_mask, + key->compressed_multisample_layout_mask); + + for (unsigned int i = 0; i < MAX_SAMPLERS; i++) { + found |= key_debug(brw, "textureGather workarounds", + old_key->gen6_gather_wa[i], key->gen6_gather_wa[i]); + } return found; } @@ -268,7 +293,7 @@ brw_wm_debug_recompile(struct brw_context *brw, for (unsigned int i = 0; i < brw->cache.size; i++) { for (c = brw->cache.items[i]; c; c = c->next) { - if (c->cache_id == BRW_WM_PROG) { + if (c->cache_id == BRW_CACHE_FS_PROG) { old_key = c->key; if (old_key->program_string_id == key->program_string_id) @@ -291,6 +316,10 @@ brw_wm_debug_recompile(struct brw_context *brw, old_key->stats_wm, key->stats_wm); found |= key_debug(brw, "flat shading", old_key->flat_shade, key->flat_shade); + found |= key_debug(brw, "per-sample shading", + old_key->persample_shading, key->persample_shading); + found |= key_debug(brw, "per-sample shading and 2x MSAA", + old_key->persample_2x, key->persample_2x); found |= key_debug(brw, "number of color buffers", old_key->nr_color_regions, key->nr_color_regions); found |= key_debug(brw, "MRT alpha test or alpha-to-coverage", @@ -348,7 +377,7 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx, int unit_id = prog->SamplerUnits[s]; const struct gl_texture_unit *unit = &ctx->Texture.Unit[unit_id]; - if (unit->_ReallyEnabled && unit->_Current->Target != GL_TEXTURE_BUFFER) { + if (unit->_Current && unit->_Current->Target != GL_TEXTURE_BUFFER) { const struct gl_texture_object *t = unit->_Current; const struct gl_texture_image *img = t->Image[0][t->BaseLevel]; struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit_id); @@ -363,13 +392,8 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx, if (alpha_depth || (brw->gen < 8 && !brw->is_haswell)) key->swizzles[s] = brw_get_texture_swizzle(ctx, t); - if (img->InternalFormat == GL_YCBCR_MESA) { - key->yuvtex_mask |= 1 << s; - if (img->TexFormat == MESA_FORMAT_YCBCR) - key->yuvtex_swap_mask |= 1 << s; - } - - if (sampler->MinFilter != GL_NEAREST && + if (brw->gen < 8 && + sampler->MinFilter != GL_NEAREST && sampler->MagFilter != GL_NEAREST) { if (sampler->WrapS == GL_CLAMP) key->gl_clamp_mask[0] |= 1 << s; @@ -408,6 +432,27 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx, } } +static bool +brw_wm_state_dirty (struct brw_context *brw) +{ + return brw_state_dirty(brw, + _NEW_BUFFERS | + _NEW_COLOR | + _NEW_DEPTH | + _NEW_FRAG_CLAMP | + _NEW_HINT | + _NEW_LIGHT | + _NEW_LINE | + _NEW_MULTISAMPLE | + _NEW_POLYGON | + _NEW_STENCIL | + _NEW_TEXTURE, + BRW_NEW_FRAGMENT_PROGRAM | + BRW_NEW_REDUCED_PRIMITIVE | + BRW_NEW_STATS_WM | + BRW_NEW_VUE_MAP_GEOM_OUT); +} + static void brw_wm_populate_key( struct brw_context *brw, struct brw_wm_prog_key *key ) { @@ -419,7 +464,7 @@ static void brw_wm_populate_key( struct brw_context *brw, GLuint lookup = 0; GLuint line_aa; bool program_uses_dfdy = fp->program.UsesDFdy; - bool multisample_fbo = ctx->DrawBuffer->Visual.samples > 1; + const bool multisample_fbo = _mesa_geometric_samples(ctx->DrawBuffer) > 1; memset(key, 0, sizeof(*key)); @@ -480,13 +525,8 @@ static void brw_wm_populate_key( struct brw_context *brw, key->line_aa = line_aa; /* _NEW_HINT */ - if (brw->disable_derivative_optimization) { - key->high_quality_derivatives = - ctx->Hint.FragmentShaderDerivative != GL_FASTEST; - } else { - key->high_quality_derivatives = - ctx->Hint.FragmentShaderDerivative == GL_NICEST; - } + key->high_quality_derivatives = + ctx->Hint.FragmentShaderDerivative == GL_NICEST; if (brw->gen < 6) key->stats_wm = brw->stats_wm; @@ -523,7 +563,7 @@ static void brw_wm_populate_key( struct brw_context *brw, * drawable height in order to invert the Y axis. */ if (fp->program.Base.InputsRead & VARYING_BIT_POS) { - key->drawable_height = ctx->DrawBuffer->Height; + key->drawable_height = _mesa_geometric_height(ctx->DrawBuffer); } if ((fp->program.Base.InputsRead & VARYING_BIT_POS) || program_uses_dfdy) { @@ -541,6 +581,8 @@ static void brw_wm_populate_key( struct brw_context *brw, /* Ignore sample qualifier while computing this flag. */ key->persample_shading = _mesa_get_min_invocations_per_fragment(ctx, &fp->program, true) > 1; + if (key->persample_shading) + key->persample_2x = _mesa_geometric_samples(ctx->DrawBuffer) == 2; key->compute_pos_offset = _mesa_get_min_invocations_per_fragment(ctx, &fp->program, false) > 1 && @@ -572,47 +614,26 @@ static void brw_wm_populate_key( struct brw_context *brw, key->program_string_id = fp->id; } - -static void +void brw_upload_wm_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; + struct gl_shader_program *current = ctx->_Shader->_CurrentFragmentProgram; struct brw_wm_prog_key key; struct brw_fragment_program *fp = (struct brw_fragment_program *) brw->fragment_program; + if (!brw_wm_state_dirty(brw)) + return; + brw_wm_populate_key(brw, &key); - if (!brw_search_cache(&brw->cache, BRW_WM_PROG, + if (!brw_search_cache(&brw->cache, BRW_CACHE_FS_PROG, &key, sizeof(key), &brw->wm.base.prog_offset, &brw->wm.prog_data)) { - bool success = do_wm_prog(brw, ctx->Shader._CurrentFragmentProgram, fp, - &key); + bool success = brw_codegen_wm_prog(brw, current, fp, &key); (void) success; assert(success); } brw->wm.base.prog_data = &brw->wm.prog_data->base; } - - -const struct brw_tracked_state brw_wm_prog = { - .dirty = { - .mesa = (_NEW_COLOR | - _NEW_DEPTH | - _NEW_STENCIL | - _NEW_POLYGON | - _NEW_LINE | - _NEW_HINT | - _NEW_LIGHT | - _NEW_FRAG_CLAMP | - _NEW_BUFFERS | - _NEW_TEXTURE | - _NEW_MULTISAMPLE), - .brw = (BRW_NEW_FRAGMENT_PROGRAM | - BRW_NEW_REDUCED_PRIMITIVE | - BRW_NEW_VUE_MAP_GEOM_OUT | - BRW_NEW_STATS_WM) - }, - .emit = brw_upload_wm_prog -}; -