X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fgen7_gs_state.c;h=4fe1354262e51de349a3c9e7166d3a84d171a22a;hb=06372c3fa9940b6ebbc03ebb2cdfdedc87076cc0;hp=3dd5896eee8dd3811cc7b5ecab415d45aa78ccba;hpb=d99b5b2d8218fee49b2305c95efb9ed386e91f74;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/gen7_gs_state.c b/src/mesa/drivers/dri/i965/gen7_gs_state.c index 3dd5896eee8..4fe1354262e 100644 --- a/src/mesa/drivers/dri/i965/gen7_gs_state.c +++ b/src/mesa/drivers/dri/i965/gen7_gs_state.c @@ -26,35 +26,6 @@ #include "brw_defines.h" #include "intel_batchbuffer.h" - -static void -gen7_upload_gs_push_constants(struct brw_context *brw) -{ - /* BRW_NEW_GEOMETRY_PROGRAM */ - const struct brw_geometry_program *vp = - (struct brw_geometry_program *) brw->geometry_program; - if (!vp) - return; - - /* CACHE_NEW_GS_PROG */ - const struct brw_vec4_prog_data *prog_data = &brw->gs.prog_data->base; - struct brw_stage_state *stage_state = &brw->gs.base; - - gen6_upload_vec4_push_constants(brw, &vp->program.Base, prog_data, - stage_state, AUB_TRACE_VS_CONSTANTS); -} - -const struct brw_tracked_state gen7_gs_push_constants = { - .dirty = { - .mesa = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS, - .brw = (BRW_NEW_BATCH | - BRW_NEW_GEOMETRY_PROGRAM), - .cache = CACHE_NEW_GS_PROG, - }, - .emit = gen7_upload_gs_push_constants, -}; - - static void upload_gs_state(struct brw_context *brw) { @@ -66,31 +37,34 @@ upload_gs_state(struct brw_context *brw) /* CACHE_NEW_GS_PROG */ const struct brw_vec4_prog_data *prog_data = &brw->gs.prog_data->base; - /* BRW_NEW_GS_BINDING_TABLE */ - BEGIN_BATCH(2); - OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_GS << 16 | (2 - 2)); - OUT_BATCH(stage_state->bind_bo_offset); - ADVANCE_BATCH(); - - /* CACHE_NEW_SAMPLER */ - BEGIN_BATCH(2); - OUT_BATCH(_3DSTATE_SAMPLER_STATE_POINTERS_GS << 16 | (2 - 2)); - OUT_BATCH(stage_state->sampler_offset); - ADVANCE_BATCH(); - - gen7_upload_constant_state(brw, stage_state, active, _3DSTATE_CONSTANT_GS); + /** + * From Graphics BSpec: 3D-Media-GPGPU Engine > 3D Pipeline Stages > + * Geometry > Geometry Shader > State: + * + * "Note: Because of corruption in IVB:GT2, software needs to flush the + * whole fixed function pipeline when the GS enable changes value in + * the 3DSTATE_GS." + * + * The hardware architects have clarified that in this context "flush the + * whole fixed function pipeline" means to emit a PIPE_CONTROL with the "CS + * Stall" bit set. + */ + if (!brw->is_haswell && brw->gt == 2 && brw->gs.enabled != active) + gen7_emit_cs_stall_flush(brw); if (active) { BEGIN_BATCH(7); OUT_BATCH(_3DSTATE_GS << 16 | (7 - 2)); OUT_BATCH(stage_state->prog_offset); OUT_BATCH(((ALIGN(stage_state->sampler_count, 4)/4) << - GEN6_GS_SAMPLER_COUNT_SHIFT)); + GEN6_GS_SAMPLER_COUNT_SHIFT) | + ((brw->gs.prog_data->base.base.binding_table.size_bytes / 4) << + GEN6_GS_BINDING_TABLE_ENTRY_COUNT_SHIFT)); - if (brw->gs.prog_data->base.total_scratch) { + if (brw->gs.prog_data->base.base.total_scratch) { OUT_RELOC(stage_state->scratch_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, - ffs(brw->gs.prog_data->base.total_scratch) - 11); + ffs(brw->gs.prog_data->base.base.total_scratch) - 11); } else { OUT_BATCH(0); } @@ -103,16 +77,46 @@ upload_gs_state(struct brw_context *brw) (prog_data->urb_read_length << GEN6_GS_URB_READ_LENGTH_SHIFT) | (0 << GEN6_GS_URB_ENTRY_READ_OFFSET_SHIFT) | - (prog_data->dispatch_grf_start_reg << + (prog_data->base.dispatch_grf_start_reg << GEN6_GS_DISPATCH_START_GRF_SHIFT); + + /* Note: the meaning of the GEN7_GS_REORDER_TRAILING bit changes between + * Ivy Bridge and Haswell. + * + * On Ivy Bridge, setting this bit causes the vertices of a triangle + * strip to be delivered to the geometry shader in an order that does + * not strictly follow the OpenGL spec, but preserves triangle + * orientation. For example, if the vertices are (1, 2, 3, 4, 5), then + * the geometry shader sees triangles: + * + * (1, 2, 3), (2, 4, 3), (3, 4, 5) + * + * (Clearing the bit is even worse, because it fails to preserve + * orientation). + * + * Triangle strips with adjacency always ordered in a way that preserves + * triangle orientation but does not strictly follow the OpenGL spec, + * regardless of the setting of this bit. + * + * On Haswell, both triangle strips and triangle strips with adjacency + * are always ordered in a way that preserves triangle orientation. + * Setting this bit causes the ordering to strictly follow the OpenGL + * spec. + * + * So in either case we want to set the bit. Unfortunately on Ivy + * Bridge this will get the order close to correct but not perfect. + */ uint32_t dw5 = ((brw->max_gs_threads - 1) << max_threads_shift) | (brw->gs.prog_data->control_data_header_size_hwords << GEN7_GS_CONTROL_DATA_HEADER_SIZE_SHIFT) | - GEN7_GS_DISPATCH_MODE_DUAL_OBJECT | + ((brw->gs.prog_data->invocations - 1) << + GEN7_GS_INSTANCE_CONTROL_SHIFT) | + brw->gs.prog_data->dispatch_mode | GEN6_GS_STATISTICS_ENABLE | (brw->gs.prog_data->include_primitive_id ? GEN7_GS_INCLUDE_PRIMITIVE_ID : 0) | + GEN7_GS_REORDER_TRAILING | GEN7_GS_ENABLE; uint32_t dw6 = 0; @@ -144,17 +148,16 @@ upload_gs_state(struct brw_context *brw) OUT_BATCH(0); ADVANCE_BATCH(); } + brw->gs.enabled = active; } const struct brw_tracked_state gen7_gs_state = { .dirty = { - .mesa = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS, + .mesa = _NEW_TRANSFORM, .brw = (BRW_NEW_CONTEXT | BRW_NEW_GEOMETRY_PROGRAM | - BRW_NEW_GS_BINDING_TABLE | - BRW_NEW_BATCH | - BRW_NEW_PUSH_CONSTANT_ALLOCATION), - .cache = CACHE_NEW_GS_PROG | CACHE_NEW_SAMPLER + BRW_NEW_BATCH), + .cache = CACHE_NEW_GS_PROG }, .emit = upload_gs_state, };