From: Chia-I Wu Date: Sat, 28 Dec 2013 07:57:49 +0000 (+0800) Subject: ilo: add HiZ op support to the pipelines X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=127fbc086ba9365e9304843af09fe730edb1d389;p=mesa.git ilo: add HiZ op support to the pipelines Add blitter functions to perform Depth Buffer Clear, Depth Buffer Resolve, and Hierarchical Depth Buffer Resolve. Those functions set ilo_blitter up and pass it to the pipelines to emit the commands. --- diff --git a/src/gallium/drivers/ilo/Makefile.sources b/src/gallium/drivers/ilo/Makefile.sources index 1612a774519..d109af0097c 100644 --- a/src/gallium/drivers/ilo/Makefile.sources +++ b/src/gallium/drivers/ilo/Makefile.sources @@ -8,6 +8,7 @@ C_SOURCES := \ ilo_blitter.c \ ilo_blitter_blt.c \ ilo_blitter_pipe.c \ + ilo_blitter_rectlist.c \ ilo_context.c \ ilo_cp.c \ ilo_format.c \ diff --git a/src/gallium/drivers/ilo/ilo_3d.c b/src/gallium/drivers/ilo/ilo_3d.c index c7e5014075a..5f0f2312f75 100644 --- a/src/gallium/drivers/ilo/ilo_3d.c +++ b/src/gallium/drivers/ilo/ilo_3d.c @@ -156,7 +156,7 @@ ilo_3d_release_render_ring(struct ilo_cp *cp, void *data) ilo_3d_pause_queries(hw3d); } -static void +void ilo_3d_own_render_ring(struct ilo_3d *hw3d) { ilo_cp_set_ring(hw3d->cp, ILO_CP_RING_RENDER); diff --git a/src/gallium/drivers/ilo/ilo_3d.h b/src/gallium/drivers/ilo/ilo_3d.h index f73b8177a4c..694820d953f 100644 --- a/src/gallium/drivers/ilo/ilo_3d.h +++ b/src/gallium/drivers/ilo/ilo_3d.h @@ -73,6 +73,9 @@ ilo_3d_destroy(struct ilo_3d *hw3d); void ilo_3d_cp_flushed(struct ilo_3d *hw3d); +void +ilo_3d_own_render_ring(struct ilo_3d *hw3d); + void ilo_3d_begin_query(struct ilo_context *ilo, struct ilo_query *q); diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline.c b/src/gallium/drivers/ilo/ilo_3d_pipeline.c index c4e133ec57b..ca02b351370 100644 --- a/src/gallium/drivers/ilo/ilo_3d_pipeline.c +++ b/src/gallium/drivers/ilo/ilo_3d_pipeline.c @@ -28,6 +28,7 @@ #include "util/u_prim.h" #include "intel_winsys.h" +#include "ilo_blitter.h" #include "ilo_context.h" #include "ilo_cp.h" #include "ilo_state.h" @@ -258,6 +259,48 @@ ilo_3d_pipeline_emit_write_depth_count(struct ilo_3d_pipeline *p, p->emit_write_depth_count(p, bo, index); } +void +ilo_3d_pipeline_emit_rectlist(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter) +{ + const int max_len = ilo_3d_pipeline_estimate_size(p, + ILO_3D_PIPELINE_RECTLIST, blitter); + + if (max_len > ilo_cp_space(p->cp)) + ilo_cp_flush(p->cp, "out of space"); + + while (true) { + struct ilo_cp_jmp_buf jmp; + int err; + + /* we will rewind if aperture check below fails */ + ilo_cp_setjmp(p->cp, &jmp); + + handle_invalid_batch_bo(p, false); + + ilo_cp_assert_no_implicit_flush(p->cp, true); + p->emit_rectlist(p, blitter); + ilo_cp_assert_no_implicit_flush(p->cp, false); + + err = intel_winsys_check_aperture_space(blitter->ilo->winsys, + &p->cp->bo, 1); + if (err) { + /* rewind */ + ilo_cp_longjmp(p->cp, &jmp); + + /* flush and try again */ + if (!ilo_cp_empty(p->cp)) { + ilo_cp_flush(p->cp, "out of aperture"); + continue; + } + } + + break; + } + + ilo_3d_pipeline_invalidate(p, ILO_3D_PIPELINE_INVALIDATE_HW); +} + void ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p, unsigned sample_count, diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline.h b/src/gallium/drivers/ilo/ilo_3d_pipeline.h index 5353ae99f81..0574d7479e6 100644 --- a/src/gallium/drivers/ilo/ilo_3d_pipeline.h +++ b/src/gallium/drivers/ilo/ilo_3d_pipeline.h @@ -32,6 +32,7 @@ #include "ilo_gpe.h" struct intel_bo; +struct ilo_blitter; struct ilo_cp; struct ilo_context; @@ -49,6 +50,7 @@ enum ilo_3d_pipeline_action { ILO_3D_PIPELINE_FLUSH, ILO_3D_PIPELINE_WRITE_TIMESTAMP, ILO_3D_PIPELINE_WRITE_DEPTH_COUNT, + ILO_3D_PIPELINE_RECTLIST, }; /** @@ -81,6 +83,9 @@ struct ilo_3d_pipeline { void (*emit_write_depth_count)(struct ilo_3d_pipeline *pipeline, struct intel_bo *bo, int index); + void (*emit_rectlist)(struct ilo_3d_pipeline *pipeline, + const struct ilo_blitter *blitter); + /** * HW states. */ @@ -171,6 +176,10 @@ void ilo_3d_pipeline_emit_write_depth_count(struct ilo_3d_pipeline *p, struct intel_bo *bo, int index); +void +ilo_3d_pipeline_emit_rectlist(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter); + void ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p, unsigned sample_count, diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c index 3b6a3c41e95..ceab6fec8be 100644 --- a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c +++ b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c @@ -29,6 +29,7 @@ #include "util/u_prim.h" #include "intel_reg.h" +#include "ilo_blitter.h" #include "ilo_3d.h" #include "ilo_context.h" #include "ilo_cp.h" @@ -1518,6 +1519,178 @@ ilo_3d_pipeline_emit_write_depth_count_gen6(struct ilo_3d_pipeline *p, true, p->cp); } +static void +gen6_rectlist_vs_to_sf(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + gen6_emit_3DSTATE_CONSTANT_VS(p->dev, NULL, NULL, 0, p->cp); + gen6_emit_3DSTATE_VS(p->dev, NULL, 0, p->cp); + + gen6_wa_pipe_control_vs_const_flush(p); + + gen6_emit_3DSTATE_CONSTANT_GS(p->dev, NULL, NULL, 0, p->cp); + gen6_emit_3DSTATE_GS(p->dev, NULL, NULL, 0, p->cp); + + gen6_emit_3DSTATE_CLIP(p->dev, NULL, NULL, false, 0, p->cp); + gen6_emit_3DSTATE_SF(p->dev, NULL, NULL, p->cp); +} + +static void +gen6_rectlist_wm(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + uint32_t hiz_op; + + switch (blitter->op) { + case ILO_BLITTER_RECTLIST_CLEAR_ZS: + hiz_op = GEN6_WM_DEPTH_CLEAR; + break; + case ILO_BLITTER_RECTLIST_RESOLVE_Z: + hiz_op = GEN6_WM_DEPTH_RESOLVE; + break; + case ILO_BLITTER_RECTLIST_RESOLVE_HIZ: + hiz_op = GEN6_WM_HIERARCHICAL_DEPTH_RESOLVE; + break; + default: + hiz_op = 0; + break; + } + + gen6_emit_3DSTATE_CONSTANT_PS(p->dev, NULL, NULL, 0, p->cp); + + gen6_wa_pipe_control_wm_max_threads_stall(p); + gen6_emit_3DSTATE_WM(p->dev, NULL, 0, NULL, false, false, hiz_op, p->cp); +} + +static void +gen6_rectlist_wm_depth(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + gen6_wa_pipe_control_wm_depth_flush(p); + + if (blitter->uses & ILO_BLITTER_USE_FB_DEPTH) { + gen6_emit_3DSTATE_DEPTH_BUFFER(p->dev, + &blitter->fb.dst.u.zs, p->cp); + + gen6_emit_3DSTATE_HIER_DEPTH_BUFFER(p->dev, + &blitter->fb.dst.u.zs, p->cp); + } + + if (blitter->uses & ILO_BLITTER_USE_FB_STENCIL) { + gen6_emit_3DSTATE_STENCIL_BUFFER(p->dev, + &blitter->fb.dst.u.zs, p->cp); + } + + gen6_emit_3DSTATE_CLEAR_PARAMS(p->dev, + blitter->depth_clear_value, p->cp); +} + +static void +gen6_rectlist_wm_multisample(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + const uint32_t *packed_sample_pos = (blitter->fb.num_samples > 1) ? + &p->packed_sample_position_4x : &p->packed_sample_position_1x; + + gen6_wa_pipe_control_wm_multisample_flush(p); + + gen6_emit_3DSTATE_MULTISAMPLE(p->dev, blitter->fb.num_samples, + packed_sample_pos, true, p->cp); + + gen6_emit_3DSTATE_SAMPLE_MASK(p->dev, + (1 << blitter->fb.num_samples) - 1, p->cp); +} + +static void +gen6_rectlist_commands(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + gen6_wa_pipe_control_post_sync(p, false); + + gen6_rectlist_wm_multisample(p, blitter, session); + + gen6_emit_STATE_BASE_ADDRESS(p->dev, + NULL, /* General State Base */ + p->cp->bo, /* Surface State Base */ + p->cp->bo, /* Dynamic State Base */ + NULL, /* Indirect Object Base */ + NULL, /* Instruction Base */ + 0, 0, 0, 0, p->cp); + + gen6_emit_3DSTATE_VERTEX_BUFFERS(p->dev, + &blitter->ve, &blitter->vb, p->cp); + + gen6_emit_3DSTATE_VERTEX_ELEMENTS(p->dev, + &blitter->ve, false, false, p->cp); + + gen6_emit_3DSTATE_URB(p->dev, + p->dev->urb_size, 0, blitter->ve.count * 4 * sizeof(float), 0, p->cp); + /* 3DSTATE_URB workaround */ + if (p->state.gs.active) { + ilo_3d_pipeline_emit_flush_gen6(p); + p->state.gs.active = false; + } + + if (blitter->uses & + (ILO_BLITTER_USE_DSA | ILO_BLITTER_USE_CC)) { + gen6_emit_3DSTATE_CC_STATE_POINTERS(p->dev, 0, + session->DEPTH_STENCIL_STATE, session->COLOR_CALC_STATE, p->cp); + } + + gen6_rectlist_vs_to_sf(p, blitter, session); + gen6_rectlist_wm(p, blitter, session); + + if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) { + gen6_emit_3DSTATE_VIEWPORT_STATE_POINTERS(p->dev, + 0, 0, session->CC_VIEWPORT, p->cp); + } + + gen6_rectlist_wm_depth(p, blitter, session); + + gen6_emit_3DSTATE_DRAWING_RECTANGLE(p->dev, 0, 0, + blitter->fb.width, blitter->fb.height, p->cp); + + gen6_emit_3DPRIMITIVE(p->dev, &blitter->draw, NULL, true, p->cp); +} + +static void +gen6_rectlist_states(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + if (blitter->uses & ILO_BLITTER_USE_DSA) { + session->DEPTH_STENCIL_STATE = + gen6_emit_DEPTH_STENCIL_STATE(p->dev, &blitter->dsa, p->cp); + } + + if (blitter->uses & ILO_BLITTER_USE_CC) { + session->COLOR_CALC_STATE = + gen6_emit_COLOR_CALC_STATE(p->dev, &blitter->cc.stencil_ref, + blitter->cc.alpha_ref, &blitter->cc.blend_color, p->cp); + } + + if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) { + session->CC_VIEWPORT = + gen6_emit_CC_VIEWPORT(p->dev, &blitter->viewport, 1, p->cp); + } +} + +static void +ilo_3d_pipeline_emit_rectlist_gen6(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter) +{ + struct gen6_rectlist_session session; + + memset(&session, 0, sizeof(session)); + gen6_rectlist_states(p, blitter, &session); + gen6_rectlist_commands(p, blitter, &session); +} + static int gen6_pipeline_estimate_commands(const struct ilo_3d_pipeline *p, const struct ilo_context *ilo) @@ -1702,6 +1875,9 @@ ilo_3d_pipeline_estimate_size_gen6(struct ilo_3d_pipeline *p, size = ilo_gpe_gen6_estimate_command_size(p->dev, ILO_GPE_GEN6_PIPE_CONTROL, 1) * 3; break; + case ILO_3D_PIPELINE_RECTLIST: + size = 64 + 256; /* states + commands */ + break; default: assert(!"unknown 3D pipeline action"); size = 0; @@ -1719,4 +1895,5 @@ ilo_3d_pipeline_init_gen6(struct ilo_3d_pipeline *p) p->emit_flush = ilo_3d_pipeline_emit_flush_gen6; p->emit_write_timestamp = ilo_3d_pipeline_emit_write_timestamp_gen6; p->emit_write_depth_count = ilo_3d_pipeline_emit_write_depth_count_gen6; + p->emit_rectlist = ilo_3d_pipeline_emit_rectlist_gen6; } diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.h b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.h index 36609f238f1..c6f48ebbe7c 100644 --- a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.h +++ b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.h @@ -73,6 +73,12 @@ struct gen6_pipeline_session { int num_surfaces[PIPE_SHADER_TYPES]; }; +struct gen6_rectlist_session { + uint32_t DEPTH_STENCIL_STATE; + uint32_t COLOR_CALC_STATE; + uint32_t CC_VIEWPORT; +}; + void gen6_pipeline_prepare(const struct ilo_3d_pipeline *p, const struct ilo_context *ilo, diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c index a63a77e0347..40687aeeed2 100644 --- a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c +++ b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c @@ -28,7 +28,7 @@ #include "util/u_dual_blend.h" #include "intel_reg.h" -#include "ilo_common.h" +#include "ilo_blitter.h" #include "ilo_context.h" #include "ilo_cp.h" #include "ilo_gpe_gen7.h" @@ -650,6 +650,233 @@ ilo_3d_pipeline_emit_draw_gen7(struct ilo_3d_pipeline *p, gen6_pipeline_end(p, ilo, &session); } +static void +gen7_rectlist_pcb_alloc(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + /* + * Push constant buffers are only allowed to take up at most the first + * 16KB of the URB. Split the space evenly for VS and FS. + */ + const int max_size = + (p->dev->gen == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384; + const int size = max_size / 2; + int offset = 0; + + gen7_emit_3DSTATE_PUSH_CONSTANT_ALLOC_VS(p->dev, offset, size, p->cp); + offset += size; + + gen7_emit_3DSTATE_PUSH_CONSTANT_ALLOC_PS(p->dev, offset, size, p->cp); + + gen7_wa_pipe_control_cs_stall(p, true, true); +} + +static void +gen7_rectlist_urb(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + /* the first 16KB are reserved for VS and PS PCBs */ + const int offset = + (p->dev->gen == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384; + + gen7_emit_3DSTATE_URB_VS(p->dev, offset, p->dev->urb_size - offset, + blitter->ve.count * 4 * sizeof(float), p->cp); + + gen7_emit_3DSTATE_URB_GS(p->dev, offset, 0, 0, p->cp); + gen7_emit_3DSTATE_URB_HS(p->dev, offset, 0, 0, p->cp); + gen7_emit_3DSTATE_URB_DS(p->dev, offset, 0, 0, p->cp); +} + +static void +gen7_rectlist_vs_to_sf(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + gen7_emit_3DSTATE_CONSTANT_VS(p->dev, NULL, NULL, 0, p->cp); + gen6_emit_3DSTATE_VS(p->dev, NULL, 0, p->cp); + + gen7_emit_3DSTATE_CONSTANT_HS(p->dev, NULL, NULL, 0, p->cp); + gen7_emit_3DSTATE_HS(p->dev, NULL, 0, p->cp); + + gen7_emit_3DSTATE_TE(p->dev, p->cp); + + gen7_emit_3DSTATE_CONSTANT_DS(p->dev, NULL, NULL, 0, p->cp); + gen7_emit_3DSTATE_DS(p->dev, NULL, 0, p->cp); + + gen7_emit_3DSTATE_CONSTANT_GS(p->dev, NULL, NULL, 0, p->cp); + gen7_emit_3DSTATE_GS(p->dev, NULL, 0, p->cp); + + gen7_emit_3DSTATE_STREAMOUT(p->dev, 0x0, 0, false, p->cp); + + gen6_emit_3DSTATE_CLIP(p->dev, NULL, NULL, false, 0, p->cp); + + gen7_wa_pipe_control_cs_stall(p, true, true); + + gen7_emit_3DSTATE_SF(p->dev, NULL, blitter->fb.dst.base.format, p->cp); + gen7_emit_3DSTATE_SBE(p->dev, NULL, NULL, p->cp); +} + +static void +gen7_rectlist_wm(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + uint32_t hiz_op; + + switch (blitter->op) { + case ILO_BLITTER_RECTLIST_CLEAR_ZS: + hiz_op = GEN7_WM_DEPTH_CLEAR; + break; + case ILO_BLITTER_RECTLIST_RESOLVE_Z: + hiz_op = GEN7_WM_DEPTH_RESOLVE; + break; + case ILO_BLITTER_RECTLIST_RESOLVE_HIZ: + hiz_op = GEN7_WM_HIERARCHICAL_DEPTH_RESOLVE; + break; + default: + hiz_op = 0; + break; + } + + gen7_wa_pipe_control_wm_max_threads_stall(p); + gen7_emit_3DSTATE_WM(p->dev, NULL, NULL, false, hiz_op, p->cp); + + gen7_emit_3DSTATE_CONSTANT_PS(p->dev, NULL, NULL, 0, p->cp); + gen7_emit_3DSTATE_PS(p->dev, NULL, 0, false, p->cp); +} + +static void +gen7_rectlist_wm_depth(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + gen7_wa_pipe_control_wm_depth_stall(p, true); + + if (blitter->uses & ILO_BLITTER_USE_FB_DEPTH) { + gen6_emit_3DSTATE_DEPTH_BUFFER(p->dev, + &blitter->fb.dst.u.zs, p->cp); + + gen6_emit_3DSTATE_HIER_DEPTH_BUFFER(p->dev, + &blitter->fb.dst.u.zs, p->cp); + } + + if (blitter->uses & ILO_BLITTER_USE_FB_STENCIL) { + gen6_emit_3DSTATE_STENCIL_BUFFER(p->dev, + &blitter->fb.dst.u.zs, p->cp); + } + + gen7_emit_3DSTATE_CLEAR_PARAMS(p->dev, + blitter->depth_clear_value, p->cp); +} + +static void +gen7_rectlist_wm_multisample(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + const uint32_t *packed_sample_pos = + (blitter->fb.num_samples > 4) ? p->packed_sample_position_8x : + (blitter->fb.num_samples > 1) ? &p->packed_sample_position_4x : + &p->packed_sample_position_1x; + + gen7_wa_pipe_control_cs_stall(p, true, true); + + gen6_emit_3DSTATE_MULTISAMPLE(p->dev, blitter->fb.num_samples, + packed_sample_pos, true, p->cp); + + gen7_emit_3DSTATE_SAMPLE_MASK(p->dev, + (1 << blitter->fb.num_samples) - 1, blitter->fb.num_samples, p->cp); +} + +static void +gen7_rectlist_commands(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + gen7_rectlist_wm_multisample(p, blitter, session); + + gen6_emit_STATE_BASE_ADDRESS(p->dev, + NULL, /* General State Base */ + p->cp->bo, /* Surface State Base */ + p->cp->bo, /* Dynamic State Base */ + NULL, /* Indirect Object Base */ + NULL, /* Instruction Base */ + 0, 0, 0, 0, p->cp); + + gen6_emit_3DSTATE_VERTEX_BUFFERS(p->dev, + &blitter->ve, &blitter->vb, p->cp); + + gen6_emit_3DSTATE_VERTEX_ELEMENTS(p->dev, + &blitter->ve, false, false, p->cp); + + gen7_rectlist_pcb_alloc(p, blitter, session); + + /* needed for any VS-related commands */ + gen7_wa_pipe_control_vs_depth_stall(p); + + gen7_rectlist_urb(p, blitter, session); + + if (blitter->uses & ILO_BLITTER_USE_DSA) { + gen7_emit_3DSTATE_DEPTH_STENCIL_STATE_POINTERS(p->dev, + session->DEPTH_STENCIL_STATE, p->cp); + } + + if (blitter->uses & ILO_BLITTER_USE_CC) { + gen7_emit_3DSTATE_CC_STATE_POINTERS(p->dev, + session->COLOR_CALC_STATE, p->cp); + } + + gen7_rectlist_vs_to_sf(p, blitter, session); + gen7_rectlist_wm(p, blitter, session); + + if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) { + gen7_emit_3DSTATE_VIEWPORT_STATE_POINTERS_CC(p->dev, + session->CC_VIEWPORT, p->cp); + } + + gen7_rectlist_wm_depth(p, blitter, session); + + gen6_emit_3DSTATE_DRAWING_RECTANGLE(p->dev, 0, 0, + blitter->fb.width, blitter->fb.height, p->cp); + + gen7_emit_3DPRIMITIVE(p->dev, &blitter->draw, NULL, true, p->cp); +} + +static void +gen7_rectlist_states(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter, + struct gen6_rectlist_session *session) +{ + if (blitter->uses & ILO_BLITTER_USE_DSA) { + session->DEPTH_STENCIL_STATE = + gen6_emit_DEPTH_STENCIL_STATE(p->dev, &blitter->dsa, p->cp); + } + + if (blitter->uses & ILO_BLITTER_USE_CC) { + session->COLOR_CALC_STATE = + gen6_emit_COLOR_CALC_STATE(p->dev, &blitter->cc.stencil_ref, + blitter->cc.alpha_ref, &blitter->cc.blend_color, p->cp); + } + + if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) { + session->CC_VIEWPORT = + gen6_emit_CC_VIEWPORT(p->dev, &blitter->viewport, 1, p->cp); + } +} + +static void +ilo_3d_pipeline_emit_rectlist_gen7(struct ilo_3d_pipeline *p, + const struct ilo_blitter *blitter) +{ + struct gen6_rectlist_session session; + + memset(&session, 0, sizeof(session)); + gen7_rectlist_states(p, blitter, &session); + gen7_rectlist_commands(p, blitter, &session); +} + static int gen7_pipeline_estimate_commands(const struct ilo_3d_pipeline *p, const struct ilo_context *ilo) @@ -809,6 +1036,9 @@ ilo_3d_pipeline_estimate_size_gen7(struct ilo_3d_pipeline *p, size = ilo_gpe_gen7_estimate_command_size(p->dev, ILO_GPE_GEN7_PIPE_CONTROL, 1); break; + case ILO_3D_PIPELINE_RECTLIST: + size = 64 + 256; /* states + commands */ + break; default: assert(!"unknown 3D pipeline action"); size = 0; @@ -826,4 +1056,5 @@ ilo_3d_pipeline_init_gen7(struct ilo_3d_pipeline *p) p->emit_flush = ilo_3d_pipeline_emit_flush_gen6; p->emit_write_timestamp = ilo_3d_pipeline_emit_write_timestamp_gen6; p->emit_write_depth_count = ilo_3d_pipeline_emit_write_depth_count_gen6; + p->emit_rectlist = ilo_3d_pipeline_emit_rectlist_gen7; } diff --git a/src/gallium/drivers/ilo/ilo_blitter.c b/src/gallium/drivers/ilo/ilo_blitter.c index 10335920364..d08563da436 100644 --- a/src/gallium/drivers/ilo/ilo_blitter.c +++ b/src/gallium/drivers/ilo/ilo_blitter.c @@ -70,5 +70,10 @@ ilo_blitter_destroy(struct ilo_blitter *blitter) if (blitter->pipe_blitter) util_blitter_destroy(blitter->pipe_blitter); + if (blitter->buffer.res) { + struct pipe_screen *screen = blitter->ilo->base.screen; + screen->resource_destroy(screen, blitter->buffer.res); + } + FREE(blitter); } diff --git a/src/gallium/drivers/ilo/ilo_blitter.h b/src/gallium/drivers/ilo/ilo_blitter.h index 6a2a0d7022e..c2c86c04e90 100644 --- a/src/gallium/drivers/ilo/ilo_blitter.h +++ b/src/gallium/drivers/ilo/ilo_blitter.h @@ -29,14 +29,64 @@ #define ILO_BLITTER_H #include "ilo_common.h" +#include "ilo_context.h" +#include "ilo_gpe.h" + +enum ilo_blitter_uses { + ILO_BLITTER_USE_DSA = 1 << 0, + ILO_BLITTER_USE_CC = 1 << 1, + ILO_BLITTER_USE_VIEWPORT = 1 << 2, + ILO_BLITTER_USE_FB_DEPTH = 1 << 3, + ILO_BLITTER_USE_FB_STENCIL = 1 << 4, +}; + +enum ilo_blitter_rectlist_op { + ILO_BLITTER_RECTLIST_CLEAR_ZS, + ILO_BLITTER_RECTLIST_RESOLVE_Z, + ILO_BLITTER_RECTLIST_RESOLVE_HIZ, +}; -struct ilo_context; struct blitter_context; +struct pipe_resource; +struct pipe_surface; struct ilo_blitter { struct ilo_context *ilo; - struct blitter_context *pipe_blitter; + + /* + * A minimal context with the goal to send RECTLISTs down the pipeline. + */ + enum ilo_blitter_rectlist_op op; + uint32_t uses; + + bool initialized; + + struct { + struct pipe_resource *res; + unsigned offset, size; + } buffer; + + struct ilo_ve_state ve; + struct ilo_vb_state vb; + struct pipe_draw_info draw; + + struct ilo_viewport_cso viewport; + struct ilo_dsa_state dsa; + + struct { + struct pipe_stencil_ref stencil_ref; + ubyte alpha_ref; + struct pipe_blend_color blend_color; + } cc; + + uint32_t depth_clear_value; + + struct { + struct ilo_surface_cso dst; + unsigned width, height; + unsigned num_samples; + } fb; }; struct ilo_blitter * @@ -99,4 +149,20 @@ ilo_blitter_blt_clear_zs(struct ilo_blitter *blitter, unsigned x, unsigned y, unsigned width, unsigned height); +bool +ilo_blitter_rectlist_clear_zs(struct ilo_blitter *blitter, + struct pipe_surface *zs, + unsigned clear_flags, + double depth, unsigned stencil); + +void +ilo_blitter_rectlist_resolve_z(struct ilo_blitter *blitter, + struct pipe_resource *res, + unsigned level, unsigned slice); + +void +ilo_blitter_rectlist_resolve_hiz(struct ilo_blitter *blitter, + struct pipe_resource *res, + unsigned level, unsigned slice); + #endif /* ILO_BLITTER_H */ diff --git a/src/gallium/drivers/ilo/ilo_blitter_rectlist.c b/src/gallium/drivers/ilo/ilo_blitter_rectlist.c new file mode 100644 index 00000000000..6314c35fd2d --- /dev/null +++ b/src/gallium/drivers/ilo/ilo_blitter_rectlist.c @@ -0,0 +1,525 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2014 LunarG, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#include "util/u_draw.h" +#include "util/u_pack_color.h" + +#include "ilo_blitter.h" +#include "ilo_3d.h" +#include "ilo_3d_pipeline.h" +#include "ilo_gpe.h" +#include "ilo_gpe_gen6.h" /* for ve_init_cso_with_components */ + +/** + * Set the states that are invariant between all ops. + */ +static bool +ilo_blitter_set_invariants(struct ilo_blitter *blitter) +{ + struct pipe_screen *screen = blitter->ilo->base.screen; + struct pipe_resource templ; + struct pipe_vertex_element velems[2]; + struct pipe_viewport_state vp; + + if (blitter->initialized) + return true; + + blitter->buffer.size = 4096; + + /* allocate the vertex buffer */ + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_BUFFER; + templ.width0 = blitter->buffer.size; + templ.usage = PIPE_USAGE_STREAM; + templ.bind = PIPE_BIND_VERTEX_BUFFER; + blitter->buffer.res = screen->resource_create(screen, &templ); + if (!blitter->buffer.res) + return false; + + /* do not increase reference count */ + blitter->vb.states[0].buffer = blitter->buffer.res; + + /* only vertex X and Y */ + blitter->vb.states[0].stride = 2 * sizeof(float); + blitter->vb.enabled_mask = 0x1; + memset(&velems, 0, sizeof(velems)); + velems[1].src_format = PIPE_FORMAT_R32G32_FLOAT; + ilo_gpe_init_ve(blitter->ilo->dev, 2, velems, &blitter->ve); + + /* override first VE to be VUE header */ + ve_init_cso_with_components(blitter->ilo->dev, + BRW_VE1_COMPONENT_STORE_0, /* Reserved */ + BRW_VE1_COMPONENT_STORE_0, /* Render Target Array Index */ + BRW_VE1_COMPONENT_STORE_0, /* Viewport Index */ + BRW_VE1_COMPONENT_STORE_0, /* Point Width */ + &blitter->ve.cso[0]); + + /* a rectangle has 3 vertices in a RECTLIST */ + util_draw_init_info(&blitter->draw); + blitter->draw.count = 3; + + /** + * From the Haswell PRM, volume 7, page 615: + * + * "The clear value must be between the min and max depth values + * (inclusive) defined in the CC_VIEWPORT." + * + * Even though clipping and viewport transformation will be disabled, we + * still need to set up the viewport states. + */ + memset(&vp, 0, sizeof(vp)); + vp.scale[0] = 1.0f; + vp.scale[1] = 1.0f; + vp.scale[2] = 1.0f; + vp.scale[3] = 1.0f; + ilo_gpe_set_viewport_cso(blitter->ilo->dev, &vp, &blitter->viewport); + + blitter->initialized = true; + + return true; +} + +static void +ilo_blitter_set_op(struct ilo_blitter *blitter, + enum ilo_blitter_rectlist_op op) +{ + blitter->op = op; +} + +/** + * Set the rectangle primitive. + */ +static void +ilo_blitter_set_rectlist(struct ilo_blitter *blitter, + unsigned x, unsigned y, + unsigned width, unsigned height) +{ + unsigned usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED; + float vertices[3][2]; + struct pipe_box box; + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 11: + * + * "(RECTLIST) A list of independent rectangles, where only 3 vertices + * are provided per rectangle object, with the fourth vertex implied + * by the definition of a rectangle. V0=LowerRight, V1=LowerLeft, + * V2=UpperLeft. Implied V3 = V0- V1+V2." + */ + vertices[0][0] = (float) (x + width); + vertices[0][1] = (float) (y + height); + vertices[1][0] = (float) x; + vertices[1][1] = (float) (y + height); + vertices[2][0] = (float) x; + vertices[2][1] = (float) y; + + /* buffer is full */ + if (blitter->buffer.offset + sizeof(vertices) > blitter->buffer.size) { + if (!ilo_buffer_alloc_bo(ilo_buffer(blitter->buffer.res))) + usage &= ~PIPE_TRANSFER_UNSYNCHRONIZED; + + blitter->buffer.offset = 0; + } + + u_box_1d(blitter->buffer.offset, sizeof(vertices), &box); + + blitter->ilo->base.transfer_inline_write(&blitter->ilo->base, + blitter->buffer.res, 0, usage, &box, vertices, 0, 0); + + blitter->vb.states[0].buffer_offset = blitter->buffer.offset; + blitter->buffer.offset += sizeof(vertices); +} + +static void +ilo_blitter_set_clear_values(struct ilo_blitter *blitter, + uint32_t depth, ubyte stencil) +{ + blitter->depth_clear_value = depth; + blitter->cc.stencil_ref.ref_value[0] = stencil; +} + +static void +ilo_blitter_set_dsa(struct ilo_blitter *blitter, + const struct pipe_depth_stencil_alpha_state *state) +{ + ilo_gpe_init_dsa(blitter->ilo->dev, state, &blitter->dsa); +} + +static void +ilo_blitter_set_fb(struct ilo_blitter *blitter, + const struct pipe_resource *res, unsigned level, + const struct ilo_surface_cso *cso) +{ + blitter->fb.width = u_minify(res->width0, level); + blitter->fb.height = u_minify(res->height0, level); + + blitter->fb.num_samples = res->nr_samples; + if (!blitter->fb.num_samples) + blitter->fb.num_samples = 1; + + memcpy(&blitter->fb.dst, cso, sizeof(*cso)); +} + +static void +ilo_blitter_set_fb_from_surface(struct ilo_blitter *blitter, + struct pipe_surface *surf) +{ + ilo_blitter_set_fb(blitter, surf->texture, surf->u.tex.level, + (const struct ilo_surface_cso *) surf); +} + +static void +ilo_blitter_set_fb_from_resource(struct ilo_blitter *blitter, + struct pipe_resource *res, + enum pipe_format format, + unsigned level, unsigned slice) +{ + struct pipe_surface templ, *surf; + + memset(&templ, 0, sizeof(templ)); + templ.format = format; + templ.u.tex.level = level; + templ.u.tex.first_layer = slice; + templ.u.tex.last_layer = slice; + + /* if we did not call create_surface(), it would never fail */ + surf = blitter->ilo->base.create_surface(&blitter->ilo->base, res, &templ); + assert(surf); + + ilo_blitter_set_fb(blitter, res, level, + (const struct ilo_surface_cso *) surf); + + pipe_surface_reference(&surf, NULL); +} + +static void +ilo_blitter_set_uses(struct ilo_blitter *blitter, uint32_t uses) +{ + blitter->uses = uses; +} + +static void +hiz_emit_rectlist(struct ilo_blitter *blitter) +{ + struct ilo_3d *hw3d = blitter->ilo->hw3d; + struct ilo_3d_pipeline *p = hw3d->pipeline; + + ilo_3d_own_render_ring(hw3d); + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 313: + * + * "If other rendering operations have preceded this clear, a + * PIPE_CONTROL with write cache flush enabled and Z-inhibit + * disabled must be issued before the rectangle primitive used for + * the depth buffer clear operation." + * + * From the Sandy Bridge PRM, volume 2 part 1, page 314: + * + * "Depth buffer clear pass must be followed by a PIPE_CONTROL + * command with DEPTH_STALL bit set and Then followed by Depth + * FLUSH" + * + * But the pipeline has to be flushed both before and after not only + * because of these workarounds. We need them for reasons such as + * + * - we may sample from a texture that was rendered to + * - we may sample from the fb shortly after + */ + if (!ilo_cp_empty(p->cp)) + ilo_3d_pipeline_emit_flush(p); + + ilo_3d_pipeline_emit_rectlist(p, blitter); + + ilo_3d_pipeline_emit_flush(p); +} + +/** + * This must be called after ilo_blitter_set_fb(). + */ +static void +hiz_set_rectlist(struct ilo_blitter *blitter, bool aligned) +{ + unsigned width = blitter->fb.width; + unsigned height = blitter->fb.height; + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 313-314: + * + * "A rectangle primitive representing the clear area is delivered. The + * primitive must adhere to the following restrictions on size: + * + * - If Number of Multisamples is NUMSAMPLES_1, the rectangle must be + * aligned to an 8x4 pixel block relative to the upper left corner + * of the depth buffer, and contain an integer number of these pixel + * blocks, and all 8x4 pixels must be lit. + * + * - If Number of Multisamples is NUMSAMPLES_4, the rectangle must be + * aligned to a 4x2 pixel block (8x4 sample block) relative to the + * upper left corner of the depth buffer, and contain an integer + * number of these pixel blocks, and all samples of the 4x2 pixels + * must be lit + * + * - If Number of Multisamples is NUMSAMPLES_8, the rectangle must be + * aligned to a 2x2 pixel block (8x4 sample block) relative to the + * upper left corner of the depth buffer, and contain an integer + * number of these pixel blocks, and all samples of the 2x2 pixels + * must be list." + * + * "The following is required when performing a depth buffer resolve: + * + * - A rectangle primitive of the same size as the previous depth + * buffer clear operation must be delivered, and depth buffer state + * cannot have changed since the previous depth buffer clear + * operation." + * + * Making the RECTLIST aligned to 8x4 is easy. But how about + * 3DSTATE_DRAWING_RECTANGLE and 3DSTATE_DEPTH_BUFFER? Since we use + * HALIGN_8 and VALIGN_4 for depth buffers, we can safely align the drawing + * rectangle, except that the PRM requires the drawing rectangle to be + * clampped to the render target boundary. For 3DSTATE_DEPTH_BUFFER, we + * cannot align the Width and Height fields if level or slice is greater + * than zero. + */ + if (aligned) { + switch (blitter->fb.num_samples) { + case 1: + width = align(width, 8); + height = align(height, 4); + break; + case 2: + width = align(width, 4); + height = align(height, 4); + break; + case 4: + width = align(width, 4); + height = align(height, 2); + break; + case 8: + default: + width = align(width, 2); + height = align(height, 2); + break; + } + } + + ilo_blitter_set_rectlist(blitter, 0, 0, width, height); +} + +static bool +hiz_can_clear_zs(const struct ilo_blitter *blitter, + const struct ilo_texture *tex) +{ + if (blitter->ilo->dev->gen > ILO_GEN(6)) + return true; + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 314: + * + * Several cases exist where Depth Buffer Clear cannot be enabled (the + * legacy method of clearing must be performed): + * + * - If the depth buffer format is D32_FLOAT_S8X24_UINT or + * D24_UNORM_S8_UINT. + * + * - If stencil test is enabled but the separate stencil buffer is + * disabled. + * + * - [DevSNB-A{W/A}]: ... + * + * - [DevSNB{W/A}]: When depth buffer format is D16_UNORM and the + * width of the map (LOD0) is not multiple of 16, fast clear + * optimization must be disabled. + */ + switch (tex->bo_format) { + case PIPE_FORMAT_Z16_UNORM: + if (tex->base.width0 % 16) + return false; + break; + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + assert(!"HiZ with combined depth/stencil"); + return false; + break; + default: + break; + } + + return true; +} + +bool +ilo_blitter_rectlist_clear_zs(struct ilo_blitter *blitter, + struct pipe_surface *zs, + unsigned clear_flags, + double depth, unsigned stencil) +{ + struct ilo_texture *tex = ilo_texture(zs->texture); + struct pipe_depth_stencil_alpha_state dsa_state; + uint32_t uses; + + if (!tex->hiz.bo) + return false; + + if (!hiz_can_clear_zs(blitter, tex)) + return false; + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 313-314: + * + * "- Depth Test Enable must be disabled and Depth Buffer Write Enable + * must be enabled (if depth is being cleared). + * + * - Stencil buffer clear can be performed at the same time by + * enabling Stencil Buffer Write Enable. Stencil Test Enable must + * be enabled and Stencil Pass Depth Pass Op set to REPLACE, and the + * clear value that is placed in the stencil buffer is the Stencil + * Reference Value from COLOR_CALC_STATE. + * + * - Note also that stencil buffer clear can be performed without + * depth buffer clear. For stencil only clear, Depth Test Enable and + * Depth Buffer Write Enable must be disabled. + * + * - [DevSNB] errata: For stencil buffer only clear, the previous + * depth clear value must be delivered during the clear." + */ + memset(&dsa_state, 0, sizeof(dsa_state)); + + if (clear_flags & PIPE_CLEAR_DEPTH) + dsa_state.depth.writemask = true; + + if (clear_flags & PIPE_CLEAR_STENCIL) { + dsa_state.stencil[0].enabled = true; + dsa_state.stencil[0].func = PIPE_FUNC_ALWAYS; + dsa_state.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; + dsa_state.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; + dsa_state.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; + + /* + * From the Ivy Bridge PRM, volume 2 part 1, page 277: + * + * "Additionally the following must be set to the correct values. + * + * - DEPTH_STENCIL_STATE::Stencil Write Mask must be 0xFF + * - DEPTH_STENCIL_STATE::Stencil Test Mask must be 0xFF + * - DEPTH_STENCIL_STATE::Back Face Stencil Write Mask must be 0xFF + * - DEPTH_STENCIL_STATE::Back Face Stencil Test Mask must be 0xFF" + */ + dsa_state.stencil[0].valuemask = 0xff; + dsa_state.stencil[0].writemask = 0xff; + dsa_state.stencil[1].valuemask = 0xff; + dsa_state.stencil[1].writemask = 0xff; + } + + ilo_blitter_set_invariants(blitter); + ilo_blitter_set_op(blitter, ILO_BLITTER_RECTLIST_CLEAR_ZS); + + ilo_blitter_set_dsa(blitter, &dsa_state); + ilo_blitter_set_clear_values(blitter, + util_pack_z(zs->format, depth), (ubyte) stencil); + ilo_blitter_set_fb_from_surface(blitter, zs); + + uses = ILO_BLITTER_USE_DSA; + if (clear_flags & PIPE_CLEAR_DEPTH) + uses |= ILO_BLITTER_USE_VIEWPORT | ILO_BLITTER_USE_FB_DEPTH; + if (clear_flags & PIPE_CLEAR_STENCIL) + uses |= ILO_BLITTER_USE_CC | ILO_BLITTER_USE_FB_STENCIL; + ilo_blitter_set_uses(blitter, uses); + + hiz_set_rectlist(blitter, true); + hiz_emit_rectlist(blitter); + + return true; +} + +void +ilo_blitter_rectlist_resolve_z(struct ilo_blitter *blitter, + struct pipe_resource *res, + unsigned level, unsigned slice) +{ + struct ilo_texture *tex = ilo_texture(res); + struct pipe_depth_stencil_alpha_state dsa_state; + + if (!tex->hiz.bo) + return; + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 314: + * + * "Depth Test Enable must be enabled with the Depth Test Function set + * to NEVER. Depth Buffer Write Enable must be enabled. Stencil Test + * Enable and Stencil Buffer Write Enable must be disabled." + */ + memset(&dsa_state, 0, sizeof(dsa_state)); + dsa_state.depth.writemask = true; + dsa_state.depth.enabled = true; + dsa_state.depth.func = PIPE_FUNC_NEVER; + + ilo_blitter_set_invariants(blitter); + ilo_blitter_set_op(blitter, ILO_BLITTER_RECTLIST_RESOLVE_Z); + + ilo_blitter_set_dsa(blitter, &dsa_state); + ilo_blitter_set_fb_from_resource(blitter, res, res->format, level, slice); + ilo_blitter_set_uses(blitter, + ILO_BLITTER_USE_DSA | ILO_BLITTER_USE_FB_DEPTH); + + hiz_set_rectlist(blitter, true); + hiz_emit_rectlist(blitter); +} + +void +ilo_blitter_rectlist_resolve_hiz(struct ilo_blitter *blitter, + struct pipe_resource *res, + unsigned level, unsigned slice) +{ + struct ilo_texture *tex = ilo_texture(res); + struct pipe_depth_stencil_alpha_state dsa_state; + + if (!tex->hiz.bo) + return; + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 315: + * + * "(Hierarchical Depth Buffer Resolve) Depth Test Enable must be + * disabled. Depth Buffer Write Enable must be enabled. Stencil Test + * Enable and Stencil Buffer Write Enable must be disabled." + */ + memset(&dsa_state, 0, sizeof(dsa_state)); + dsa_state.depth.writemask = true; + + ilo_blitter_set_invariants(blitter); + ilo_blitter_set_op(blitter, ILO_BLITTER_RECTLIST_RESOLVE_HIZ); + + ilo_blitter_set_dsa(blitter, &dsa_state); + ilo_blitter_set_fb_from_resource(blitter, res, res->format, level, slice); + ilo_blitter_set_uses(blitter, + ILO_BLITTER_USE_DSA | ILO_BLITTER_USE_FB_DEPTH); + + hiz_set_rectlist(blitter, false); + hiz_emit_rectlist(blitter); +}