diff options
Diffstat (limited to 'src/mesa/drivers/dri/i965/gen8_depth_state.c')
-rw-r--r-- | src/mesa/drivers/dri/i965/gen8_depth_state.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/gen8_depth_state.c b/src/mesa/drivers/dri/i965/gen8_depth_state.c index f30ff289c72..379a2c34905 100644 --- a/src/mesa/drivers/dri/i965/gen8_depth_state.c +++ b/src/mesa/drivers/dri/i965/gen8_depth_state.c @@ -203,3 +203,106 @@ gen8_emit_depth_stencil_hiz(struct brw_context *brw, brw->depthstencil.stencil_offset, hiz, width, height, depth, lod, min_array_element); } + +/** + * Emit packets to perform a depth/HiZ resolve or fast depth/stencil clear. + * + * See the "Optimized Depth Buffer Clear and/or Stencil Buffer Clear" section + * of the hardware documentation for details. + */ +void +gen8_hiz_exec(struct brw_context *brw, struct intel_mipmap_tree *mt, + unsigned int level, unsigned int layer, enum gen6_hiz_op op) +{ + if (op == GEN6_HIZ_OP_NONE) + return; + + assert(mt->first_level == 0); + assert(mt->logical_depth0 >= 1); + + /* The basic algorithm is: + * - If needed, emit 3DSTATE_{DEPTH,HIER_DEPTH,STENCIL}_BUFFER and + * 3DSTATE_CLEAR_PARAMS packets to set up the relevant buffers. + * - If needed, emit 3DSTATE_DRAWING_RECTANGLE. + * - Emit 3DSTATE_WM_HZ_OP with a bit set for the particular operation. + * - Do a special PIPE_CONTROL to trigger an implicit rectangle primitive. + * - Emit 3DSTATE_WM_HZ_OP with no bits set to return to normal rendering. + */ + emit_depth_packets(brw, mt, + brw_depth_format(brw, mt->format), + BRW_SURFACE_2D, + true, /* depth writes */ + NULL, false, 0, /* no stencil for now */ + true, /* hiz */ + mt->logical_width0, + mt->logical_height0, + mt->logical_depth0, + level, + layer); /* min_array_element */ + + unsigned rect_width = minify(mt->logical_width0, level); + unsigned rect_height = minify(mt->logical_height0, level); + + BEGIN_BATCH(4); + OUT_BATCH(_3DSTATE_DRAWING_RECTANGLE << 16 | (4 - 2)); + OUT_BATCH(0); + OUT_BATCH(((rect_width - 1) & 0xffff) | ((rect_height - 1) << 16)); + OUT_BATCH(0); + ADVANCE_BATCH(); + + /* Emit 3DSTATE_WM_HZ_OP to override pipeline state for the particular + * resolve or clear operation we want to perform. + */ + uint32_t dw1 = 0; + + switch (op) { + case GEN6_HIZ_OP_DEPTH_RESOLVE: + dw1 |= GEN8_WM_HZ_DEPTH_RESOLVE; + break; + case GEN6_HIZ_OP_HIZ_RESOLVE: + dw1 |= GEN8_WM_HZ_HIZ_RESOLVE; + break; + case GEN6_HIZ_OP_DEPTH_CLEAR: + dw1 |= GEN8_WM_HZ_DEPTH_CLEAR; + break; + case GEN6_HIZ_OP_NONE: + assert(!"Should not get here."); + } + + if (mt->num_samples > 0) + dw1 |= SET_FIELD(ffs(mt->num_samples) - 1, GEN8_WM_HZ_NUM_SAMPLES); + + BEGIN_BATCH(5); + OUT_BATCH(_3DSTATE_WM_HZ_OP << 16 | (5 - 2)); + OUT_BATCH(dw1); + OUT_BATCH(0); + OUT_BATCH(SET_FIELD(rect_width, GEN8_WM_HZ_CLEAR_RECTANGLE_X_MAX) | + SET_FIELD(rect_height, GEN8_WM_HZ_CLEAR_RECTANGLE_Y_MAX)); + OUT_BATCH(SET_FIELD(0xFFFF, GEN8_WM_HZ_SAMPLE_MASK)); + ADVANCE_BATCH(); + + /* Emit a PIPE_CONTROL with "Post-Sync Operation" set to "Write Immediate + * Data", and no other bits set. This causes 3DSTATE_WM_HZ_OP's state to + * take effect, and spawns a rectangle primitive. + */ + brw_emit_pipe_control_write(brw, + PIPE_CONTROL_WRITE_IMMEDIATE, + brw->batch.workaround_bo, 0, 0, 0); + + /* Emit 3DSTATE_WM_HZ_OP again to disable the state overrides. */ + BEGIN_BATCH(5); + OUT_BATCH(_3DSTATE_WM_HZ_OP << 16 | (5 - 2)); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + ADVANCE_BATCH(); + + /* We've clobbered all of the depth packets, and the drawing rectangle, + * so we need to ensure those packets are re-emitted before the next + * primitive. + * + * Setting _NEW_DEPTH and _NEW_BUFFERS covers it, but is rather overkill. + */ + brw->state.dirty.mesa |= _NEW_DEPTH | _NEW_BUFFERS; +} |