Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2013 LunarG, Inc.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Chia-I Wu <olv@lunarg.com>
  26.  */
  27.  
  28. #include "genhw/genhw.h"
  29. #include "core/ilo_builder.h"
  30. #include "core/ilo_builder_mi.h"
  31. #include "core/ilo_builder_render.h"
  32. #include "core/intel_winsys.h"
  33. #include "util/u_prim.h"
  34.  
  35. #include "ilo_query.h"
  36. #include "ilo_render_gen.h"
  37.  
  38. /* in S1.3 */
  39. struct sample_position {
  40.    int8_t x, y;
  41. };
  42.  
  43. static const struct sample_position ilo_sample_pattern_1x[1] = {
  44.    {  0,  0 },
  45. };
  46.  
  47. static const struct sample_position ilo_sample_pattern_2x[2] = {
  48.    { -4, -4 },
  49.    {  4,  4 },
  50. };
  51.  
  52. static const struct sample_position ilo_sample_pattern_4x[4] = {
  53.    { -2, -6 },
  54.    {  6, -2 },
  55.    { -6,  2 },
  56.    {  2,  6 },
  57. };
  58.  
  59. /* \see brw_multisample_positions_8x */
  60. static const struct sample_position ilo_sample_pattern_8x[8] = {
  61.    { -1,  1 },
  62.    {  1,  5 },
  63.    {  3, -5 },
  64.    {  5,  3 },
  65.    { -7, -1 },
  66.    { -3, -7 },
  67.    {  7, -3 },
  68.    { -5,  7 },
  69. };
  70.  
  71. static const struct sample_position ilo_sample_pattern_16x[16] = {
  72.    {  0,  2 },
  73.    {  3,  0 },
  74.    { -3, -2 },
  75.    { -2, -4 },
  76.    {  4,  3 },
  77.    {  5,  1 },
  78.    {  6, -1 },
  79.    {  2, -6 },
  80.    { -4,  5 },
  81.    { -5, -5 },
  82.    { -1, -7 },
  83.    {  7, -3 },
  84.    { -7,  4 },
  85.    {  1, -8 },
  86.    { -6,  6 },
  87.    { -8,  7 },
  88. };
  89.  
  90. static uint8_t
  91. pack_sample_position(const struct sample_position *pos)
  92. {
  93.    return (pos->x + 8) << 4 | (pos->y + 8);
  94. }
  95.  
  96. static void
  97. get_sample_position(const struct sample_position *pos, float *x, float *y)
  98. {
  99.    *x = (float) (pos->x + 8) / 16.0f;
  100.    *y = (float) (pos->y + 8) / 16.0f;
  101. }
  102.  
  103. struct ilo_render *
  104. ilo_render_create(struct ilo_builder *builder)
  105. {
  106.    struct ilo_render *render;
  107.    int i;
  108.  
  109.    render = CALLOC_STRUCT(ilo_render);
  110.    if (!render)
  111.       return NULL;
  112.  
  113.    render->dev = builder->dev;
  114.    render->builder = builder;
  115.  
  116.    render->workaround_bo = intel_winsys_alloc_bo(builder->winsys,
  117.          "PIPE_CONTROL workaround", 4096, false);
  118.    if (!render->workaround_bo) {
  119.       ilo_warn("failed to allocate PIPE_CONTROL workaround bo\n");
  120.       FREE(render);
  121.       return NULL;
  122.    }
  123.  
  124.    /* pack into dwords */
  125.    render->sample_pattern_1x = pack_sample_position(ilo_sample_pattern_1x);
  126.    render->sample_pattern_2x =
  127.       pack_sample_position(&ilo_sample_pattern_2x[1]) << 8 |
  128.       pack_sample_position(&ilo_sample_pattern_2x[0]);
  129.    for (i = 0; i < 4; i++) {
  130.       render->sample_pattern_4x |=
  131.          pack_sample_position(&ilo_sample_pattern_4x[i]) << (8 * i);
  132.  
  133.       render->sample_pattern_8x[0] |=
  134.          pack_sample_position(&ilo_sample_pattern_8x[i]) << (8 * i);
  135.       render->sample_pattern_8x[1] |=
  136.          pack_sample_position(&ilo_sample_pattern_8x[i + 4]) << (8 * i);
  137.  
  138.       render->sample_pattern_16x[0] |=
  139.          pack_sample_position(&ilo_sample_pattern_16x[i]) << (8 * i);
  140.       render->sample_pattern_16x[1] |=
  141.          pack_sample_position(&ilo_sample_pattern_16x[i + 4]) << (8 * i);
  142.       render->sample_pattern_16x[2] |=
  143.          pack_sample_position(&ilo_sample_pattern_16x[i + 8]) << (8 * i);
  144.       render->sample_pattern_16x[3] |=
  145.          pack_sample_position(&ilo_sample_pattern_16x[i + 12]) << (8 * i);
  146.    }
  147.  
  148.    ilo_render_invalidate_hw(render);
  149.    ilo_render_invalidate_builder(render);
  150.  
  151.    return render;
  152. }
  153.  
  154. void
  155. ilo_render_destroy(struct ilo_render *render)
  156. {
  157.    intel_bo_unref(render->workaround_bo);
  158.    FREE(render);
  159. }
  160.  
  161. void
  162. ilo_render_get_sample_position(const struct ilo_render *render,
  163.                                unsigned sample_count,
  164.                                unsigned sample_index,
  165.                                float *x, float *y)
  166. {
  167.    const struct sample_position *pattern;
  168.  
  169.    switch (sample_count) {
  170.    case 1:
  171.       assert(sample_index < Elements(ilo_sample_pattern_1x));
  172.       pattern = ilo_sample_pattern_1x;
  173.       break;
  174.    case 2:
  175.       assert(sample_index < Elements(ilo_sample_pattern_2x));
  176.       pattern = ilo_sample_pattern_2x;
  177.       break;
  178.    case 4:
  179.       assert(sample_index < Elements(ilo_sample_pattern_4x));
  180.       pattern = ilo_sample_pattern_4x;
  181.       break;
  182.    case 8:
  183.       assert(sample_index < Elements(ilo_sample_pattern_8x));
  184.       pattern = ilo_sample_pattern_8x;
  185.       break;
  186.    case 16:
  187.       assert(sample_index < Elements(ilo_sample_pattern_16x));
  188.       pattern = ilo_sample_pattern_16x;
  189.       break;
  190.    default:
  191.       assert(!"unknown sample count");
  192.       *x = 0.5f;
  193.       *y = 0.5f;
  194.       return;
  195.       break;
  196.    }
  197.  
  198.    get_sample_position(&pattern[sample_index], x, y);
  199. }
  200.  
  201. void
  202. ilo_render_invalidate_hw(struct ilo_render *render)
  203. {
  204.    render->hw_ctx_changed = true;
  205. }
  206.  
  207. void
  208. ilo_render_invalidate_builder(struct ilo_render *render)
  209. {
  210.    render->batch_bo_changed = true;
  211.    render->state_bo_changed = true;
  212.    render->instruction_bo_changed = true;
  213.  
  214.    /* Kernel flushes everything.  Shouldn't we set all bits here? */
  215.    render->state.current_pipe_control_dw1 = 0;
  216. }
  217.  
  218. /**
  219.  * Return the command length of ilo_render_emit_flush().
  220.  */
  221. int
  222. ilo_render_get_flush_len(const struct ilo_render *render)
  223. {
  224.    int len;
  225.  
  226.    ILO_DEV_ASSERT(render->dev, 6, 8);
  227.  
  228.    len = GEN6_PIPE_CONTROL__SIZE;
  229.  
  230.    /* plus gen6_wa_pre_pipe_control() */
  231.    if (ilo_dev_gen(render->dev) == ILO_GEN(6))
  232.       len *= 3;
  233.  
  234.    return len;
  235. }
  236.  
  237. /**
  238.  * Emit PIPE_CONTROLs to flush all caches.
  239.  */
  240. void
  241. ilo_render_emit_flush(struct ilo_render *render)
  242. {
  243.    const uint32_t dw1 = GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
  244.                         GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH |
  245.                         GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
  246.                         GEN6_PIPE_CONTROL_VF_CACHE_INVALIDATE |
  247.                         GEN6_PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
  248.                         GEN6_PIPE_CONTROL_CS_STALL;
  249.    const unsigned batch_used = ilo_builder_batch_used(render->builder);
  250.  
  251.    ILO_DEV_ASSERT(render->dev, 6, 8);
  252.  
  253.    if (ilo_dev_gen(render->dev) == ILO_GEN(6))
  254.       gen6_wa_pre_pipe_control(render, dw1);
  255.  
  256.    ilo_render_pipe_control(render, dw1);
  257.  
  258.    assert(ilo_builder_batch_used(render->builder) <= batch_used +
  259.          ilo_render_get_flush_len(render));
  260. }
  261.  
  262. /**
  263.  * Return the command length of ilo_render_emit_query().
  264.  */
  265. int
  266. ilo_render_get_query_len(const struct ilo_render *render,
  267.                          unsigned query_type)
  268. {
  269.    int len;
  270.  
  271.    ILO_DEV_ASSERT(render->dev, 6, 8);
  272.  
  273.    /* always a flush or a variant of flush */
  274.    len = ilo_render_get_flush_len(render);
  275.  
  276.    switch (query_type) {
  277.    case PIPE_QUERY_OCCLUSION_COUNTER:
  278.    case PIPE_QUERY_TIMESTAMP:
  279.    case PIPE_QUERY_TIME_ELAPSED:
  280.       /* no reg */
  281.       break;
  282.    case PIPE_QUERY_PRIMITIVES_GENERATED:
  283.    case PIPE_QUERY_PRIMITIVES_EMITTED:
  284.       len += GEN6_MI_STORE_REGISTER_MEM__SIZE * 2;
  285.       break;
  286.    case PIPE_QUERY_PIPELINE_STATISTICS:
  287.       {
  288.          const int num_regs =
  289.             (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ? 10 : 8;
  290.          const int num_pads =
  291.             (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ? 1 : 3;
  292.  
  293.          len += GEN6_MI_STORE_REGISTER_MEM__SIZE * 2 * num_regs +
  294.                 GEN6_MI_STORE_DATA_IMM__SIZE * num_pads;
  295.       }
  296.       break;
  297.    default:
  298.       len = 0;
  299.       break;
  300.    }
  301.  
  302.    return len;
  303. }
  304.  
  305. /**
  306.  * Emit PIPE_CONTROLs or MI_STORE_REGISTER_MEMs to store register values.
  307.  */
  308. void
  309. ilo_render_emit_query(struct ilo_render *render,
  310.                       struct ilo_query *q, uint32_t offset)
  311. {
  312.    const uint32_t pipeline_statistics_regs[11] = {
  313.       GEN6_REG_IA_VERTICES_COUNT,
  314.       GEN6_REG_IA_PRIMITIVES_COUNT,
  315.       GEN6_REG_VS_INVOCATION_COUNT,
  316.       GEN6_REG_GS_INVOCATION_COUNT,
  317.       GEN6_REG_GS_PRIMITIVES_COUNT,
  318.       GEN6_REG_CL_INVOCATION_COUNT,
  319.       GEN6_REG_CL_PRIMITIVES_COUNT,
  320.       GEN6_REG_PS_INVOCATION_COUNT,
  321.       (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
  322.          GEN7_REG_HS_INVOCATION_COUNT : 0,
  323.       (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
  324.          GEN7_REG_DS_INVOCATION_COUNT : 0,
  325.       0,
  326.    };
  327.    const uint32_t primitives_generated_reg =
  328.       (ilo_dev_gen(render->dev) >= ILO_GEN(7) && q->index > 0) ?
  329.       GEN7_REG_SO_PRIM_STORAGE_NEEDED(q->index) :
  330.       GEN6_REG_CL_INVOCATION_COUNT;
  331.    const uint32_t primitives_emitted_reg =
  332.       (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
  333.       GEN7_REG_SO_NUM_PRIMS_WRITTEN(q->index) :
  334.       GEN6_REG_SO_NUM_PRIMS_WRITTEN;
  335.    const unsigned batch_used = ilo_builder_batch_used(render->builder);
  336.    const uint32_t *regs;
  337.    int reg_count = 0, i;
  338.    uint32_t pipe_control_dw1 = 0;
  339.  
  340.    ILO_DEV_ASSERT(render->dev, 6, 8);
  341.  
  342.    switch (q->type) {
  343.    case PIPE_QUERY_OCCLUSION_COUNTER:
  344.       pipe_control_dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL |
  345.                          GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT;
  346.       break;
  347.    case PIPE_QUERY_TIMESTAMP:
  348.    case PIPE_QUERY_TIME_ELAPSED:
  349.       pipe_control_dw1 = GEN6_PIPE_CONTROL_WRITE_TIMESTAMP;
  350.       break;
  351.    case PIPE_QUERY_PRIMITIVES_GENERATED:
  352.       regs = &primitives_generated_reg;
  353.       reg_count = 1;
  354.       break;
  355.    case PIPE_QUERY_PRIMITIVES_EMITTED:
  356.       regs = &primitives_emitted_reg;
  357.       reg_count = 1;
  358.       break;
  359.    case PIPE_QUERY_PIPELINE_STATISTICS:
  360.       regs = pipeline_statistics_regs;
  361.       reg_count = Elements(pipeline_statistics_regs);
  362.       break;
  363.    default:
  364.       break;
  365.    }
  366.  
  367.    if (pipe_control_dw1) {
  368.       assert(!reg_count);
  369.  
  370.       if (ilo_dev_gen(render->dev) == ILO_GEN(6))
  371.          gen6_wa_pre_pipe_control(render, pipe_control_dw1);
  372.  
  373.       gen6_PIPE_CONTROL(render->builder, pipe_control_dw1, q->bo, offset, 0);
  374.  
  375.       render->state.current_pipe_control_dw1 |= pipe_control_dw1;
  376.       render->state.deferred_pipe_control_dw1 &= ~pipe_control_dw1;
  377.    } else if (reg_count) {
  378.       ilo_render_emit_flush(render);
  379.    }
  380.  
  381.    for (i = 0; i < reg_count; i++) {
  382.       if (regs[i]) {
  383.          /* store lower 32 bits */
  384.          gen6_MI_STORE_REGISTER_MEM(render->builder, regs[i], q->bo, offset);
  385.          /* store higher 32 bits */
  386.          gen6_MI_STORE_REGISTER_MEM(render->builder, regs[i] + 4,
  387.                q->bo, offset + 4);
  388.       } else {
  389.          gen6_MI_STORE_DATA_IMM(render->builder, q->bo, offset, 0);
  390.       }
  391.  
  392.       offset += 8;
  393.    }
  394.  
  395.    assert(ilo_builder_batch_used(render->builder) <= batch_used +
  396.          ilo_render_get_query_len(render, q->type));
  397. }
  398.  
  399. int
  400. ilo_render_get_rectlist_len(const struct ilo_render *render,
  401.                             const struct ilo_blitter *blitter)
  402. {
  403.    ILO_DEV_ASSERT(render->dev, 6, 8);
  404.  
  405.    return ilo_render_get_rectlist_dynamic_states_len(render, blitter) +
  406.           ilo_render_get_rectlist_commands_len(render, blitter);
  407. }
  408.  
  409. void
  410. ilo_render_emit_rectlist(struct ilo_render *render,
  411.                          const struct ilo_blitter *blitter)
  412. {
  413.    struct ilo_render_rectlist_session session;
  414.  
  415.    ILO_DEV_ASSERT(render->dev, 6, 8);
  416.  
  417.    memset(&session, 0, sizeof(session));
  418.    ilo_render_emit_rectlist_dynamic_states(render, blitter, &session);
  419.    ilo_render_emit_rectlist_commands(render, blitter, &session);
  420. }
  421.  
  422. int
  423. ilo_render_get_draw_len(const struct ilo_render *render,
  424.                         const struct ilo_state_vector *vec)
  425. {
  426.    ILO_DEV_ASSERT(render->dev, 6, 8);
  427.  
  428.    return ilo_render_get_draw_dynamic_states_len(render, vec) +
  429.           ilo_render_get_draw_surface_states_len(render, vec) +
  430.           ilo_render_get_draw_commands_len(render, vec);
  431. }
  432.  
  433. static void
  434. draw_session_prepare(struct ilo_render *render,
  435.                      const struct ilo_state_vector *vec,
  436.                      struct ilo_render_draw_session *session)
  437. {
  438.    memset(session, 0, sizeof(*session));
  439.    session->pipe_dirty = vec->dirty;
  440.    session->reduced_prim = u_reduced_prim(vec->draw->mode);
  441.  
  442.    if (render->hw_ctx_changed) {
  443.       /* these should be enough to make everything uploaded */
  444.       render->batch_bo_changed = true;
  445.       render->state_bo_changed = true;
  446.       render->instruction_bo_changed = true;
  447.  
  448.       session->prim_changed = true;
  449.       session->primitive_restart_changed = true;
  450.    } else {
  451.       session->prim_changed =
  452.          (render->state.reduced_prim != session->reduced_prim);
  453.       session->primitive_restart_changed =
  454.          (render->state.primitive_restart != vec->draw->primitive_restart);
  455.    }
  456. }
  457.  
  458. static void
  459. draw_session_end(struct ilo_render *render,
  460.                  const struct ilo_state_vector *vec,
  461.                  struct ilo_render_draw_session *session)
  462. {
  463.    render->hw_ctx_changed = false;
  464.  
  465.    render->batch_bo_changed = false;
  466.    render->state_bo_changed = false;
  467.    render->instruction_bo_changed = false;
  468.  
  469.    render->state.reduced_prim = session->reduced_prim;
  470.    render->state.primitive_restart = vec->draw->primitive_restart;
  471. }
  472.  
  473. void
  474. ilo_render_emit_draw(struct ilo_render *render,
  475.                      const struct ilo_state_vector *vec)
  476. {
  477.    struct ilo_render_draw_session session;
  478.  
  479.    ILO_DEV_ASSERT(render->dev, 6, 8);
  480.  
  481.    draw_session_prepare(render, vec, &session);
  482.  
  483.    /* force all states to be uploaded if the state bo changed */
  484.    if (render->state_bo_changed)
  485.       session.pipe_dirty = ILO_DIRTY_ALL;
  486.    else
  487.       session.pipe_dirty = vec->dirty;
  488.  
  489.    ilo_render_emit_draw_dynamic_states(render, vec, &session);
  490.    ilo_render_emit_draw_surface_states(render, vec, &session);
  491.  
  492.    /* force all commands to be uploaded if the HW context changed */
  493.    if (render->hw_ctx_changed)
  494.       session.pipe_dirty = ILO_DIRTY_ALL;
  495.    else
  496.       session.pipe_dirty = vec->dirty;
  497.  
  498.    ilo_render_emit_draw_commands(render, vec, &session);
  499.  
  500.    draw_session_end(render, vec, &session);
  501. }
  502.  
  503. int
  504. ilo_render_get_launch_grid_len(const struct ilo_render *render,
  505.                                const struct ilo_state_vector *vec)
  506. {
  507.    ILO_DEV_ASSERT(render->dev, 7, 7.5);
  508.  
  509.    return ilo_render_get_launch_grid_surface_states_len(render, vec) +
  510.           ilo_render_get_launch_grid_dynamic_states_len(render, vec) +
  511.           ilo_render_get_launch_grid_commands_len(render, vec);
  512. }
  513.  
  514. void
  515. ilo_render_emit_launch_grid(struct ilo_render *render,
  516.                             const struct ilo_state_vector *vec,
  517.                             const unsigned thread_group_offset[3],
  518.                             const unsigned thread_group_dim[3],
  519.                             unsigned thread_group_size,
  520.                             const struct pipe_constant_buffer *input,
  521.                             uint32_t pc)
  522. {
  523.    struct ilo_render_launch_grid_session session;
  524.  
  525.    ILO_DEV_ASSERT(render->dev, 7, 7.5);
  526.  
  527.    assert(input->buffer);
  528.  
  529.    memset(&session, 0, sizeof(session));
  530.  
  531.    session.thread_group_offset = thread_group_offset;
  532.    session.thread_group_dim = thread_group_dim;
  533.    session.thread_group_size = thread_group_size;
  534.    session.input = input;
  535.    session.pc = pc;
  536.  
  537.    ilo_render_emit_launch_grid_surface_states(render, vec, &session);
  538.    ilo_render_emit_launch_grid_dynamic_states(render, vec, &session);
  539.    ilo_render_emit_launch_grid_commands(render, vec, &session);
  540. }
  541.