From: Chia-I Wu Date: Mon, 15 Jun 2015 07:17:45 +0000 (+0800) Subject: ilo: add ilo_state_sol_buffer X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e3372c4bfb8d5960714651ca7d3f1acc0018a8fa;p=mesa.git ilo: add ilo_state_sol_buffer It serves the same purpose as ilo_state_vertex_buffer does. --- diff --git a/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h b/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h index 6a45d701f1d..398586bbad8 100644 --- a/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h +++ b/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h @@ -756,11 +756,13 @@ gen7_3DSTATE_STREAMOUT(struct ilo_builder *builder, dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_STREAMOUT) | (cmd_len - 2); /* see sol_set_gen7_3DSTATE_STREAMOUT() */ - dw[1] = sol->so[0]; - dw[2] = sol->so[1]; + dw[1] = sol->streamout[0]; + dw[2] = sol->streamout[1]; if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) { - dw[3] = sol->so[2]; - dw[4] = sol->so[3]; + dw[3] = sol->strides[1] << GEN8_SO_DW3_BUFFER1_PITCH__SHIFT | + sol->strides[0] << GEN8_SO_DW3_BUFFER0_PITCH__SHIFT; + dw[4] = sol->strides[3] << GEN8_SO_DW4_BUFFER3_PITCH__SHIFT | + sol->strides[2] << GEN8_SO_DW4_BUFFER2_PITCH__SHIFT; } } @@ -797,8 +799,8 @@ gen7_3DSTATE_SO_DECL_LIST(struct ilo_builder *builder, dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_SO_DECL_LIST) | (cmd_len - 2); /* see sol_set_gen7_3DSTATE_SO_DECL_LIST() */ - dw[1] = sol->so[4]; - dw[2] = sol->so[5]; + dw[1] = sol->so_decl[0]; + dw[2] = sol->so_decl[1]; memcpy(&dw[3], sol->decl, sizeof(sol->decl[0]) * sol->decl_count); if (sol->decl_count < cmd_decl_count) { @@ -808,74 +810,77 @@ gen7_3DSTATE_SO_DECL_LIST(struct ilo_builder *builder, } static inline void -gen7_3DSTATE_SO_BUFFER(struct ilo_builder *builder, int index, int stride, - const struct pipe_stream_output_target *so_target) +gen7_3DSTATE_SO_BUFFER(struct ilo_builder *builder, + const struct ilo_state_sol *sol, + const struct ilo_state_sol_buffer *sb, + uint8_t buffer) { - const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 8 : 4; - struct ilo_buffer *buf; - int start, end; + const uint8_t cmd_len = 4; uint32_t *dw; unsigned pos; - ILO_DEV_ASSERT(builder->dev, 7, 8); - - buf = ilo_buffer(so_target->buffer); - - /* DWord-aligned */ - assert(stride % 4 == 0); - assert(so_target->buffer_offset % 4 == 0); + ILO_DEV_ASSERT(builder->dev, 7, 7.5); - stride &= ~3; - start = so_target->buffer_offset & ~3; - end = (start + so_target->buffer_size) & ~3; + assert(buffer < ILO_STATE_SOL_MAX_BUFFER_COUNT); pos = ilo_builder_batch_pointer(builder, cmd_len, &dw); dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_SO_BUFFER) | (cmd_len - 2); - dw[1] = index << GEN7_SO_BUF_DW1_INDEX__SHIFT | - stride; - - if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) { - dw[1] |= builder->mocs << GEN8_SO_BUF_DW1_MOCS__SHIFT; - - dw[4] = end - start; - dw[5] = 0; - dw[6] = 0; - dw[7] = 0; - - ilo_builder_batch_reloc64(builder, pos + 2, - buf->bo, start, INTEL_RELOC_WRITE); + /* see sol_buffer_set_gen7_3dstate_so_buffer() */ + dw[1] = buffer << GEN7_SO_BUF_DW1_INDEX__SHIFT | + builder->mocs << GEN7_SO_BUF_DW1_MOCS__SHIFT | + sol->strides[buffer] << GEN7_SO_BUF_DW1_PITCH__SHIFT; + + if (sb->need_bo) { + ilo_builder_batch_reloc(builder, pos + 2, sb->bo, + sb->so_buf[0], INTEL_RELOC_WRITE); + ilo_builder_batch_reloc(builder, pos + 3, sb->bo, + sb->so_buf[1], INTEL_RELOC_WRITE); } else { - dw[1] |= builder->mocs << GEN7_SO_BUF_DW1_MOCS__SHIFT; - - ilo_builder_batch_reloc(builder, pos + 2, - buf->bo, start, INTEL_RELOC_WRITE); - ilo_builder_batch_reloc(builder, pos + 3, - buf->bo, end, INTEL_RELOC_WRITE); + dw[2] = 0; + dw[3] = 0; } } static inline void -gen7_disable_3DSTATE_SO_BUFFER(struct ilo_builder *builder, int index) +gen8_3DSTATE_SO_BUFFER(struct ilo_builder *builder, + const struct ilo_state_sol *sol, + const struct ilo_state_sol_buffer *sb, + uint8_t buffer) { - const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 8 : 4; + const uint8_t cmd_len = 8; uint32_t *dw; + unsigned pos; - ILO_DEV_ASSERT(builder->dev, 7, 8); + ILO_DEV_ASSERT(builder->dev, 8, 8); - ilo_builder_batch_pointer(builder, cmd_len, &dw); + pos = ilo_builder_batch_pointer(builder, cmd_len, &dw); dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_SO_BUFFER) | (cmd_len - 2); - dw[1] = index << GEN7_SO_BUF_DW1_INDEX__SHIFT; - dw[2] = 0; - dw[3] = 0; + /* see sol_buffer_set_gen8_3dstate_so_buffer() */ + dw[1] = sb->so_buf[0] | + buffer << GEN7_SO_BUF_DW1_INDEX__SHIFT | + builder->mocs << GEN8_SO_BUF_DW1_MOCS__SHIFT; + + if (sb->need_bo) { + ilo_builder_batch_reloc64(builder, pos + 2, sb->bo, + sb->so_buf[1], INTEL_RELOC_WRITE); + } else { + dw[2] = 0; + dw[3] = 0; + } - if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) { - dw[4] = 0; + dw[4] = sb->so_buf[2]; + + if (sb->need_write_offset_bo) { + ilo_builder_batch_reloc64(builder, pos + 5, sb->write_offset_bo, + sizeof(uint32_t) * buffer, INTEL_RELOC_WRITE); + } else { dw[5] = 0; dw[6] = 0; - dw[7] = 0; } + + dw[7] = sb->so_buf[3]; } static inline void diff --git a/src/gallium/drivers/ilo/core/ilo_state_sol.c b/src/gallium/drivers/ilo/core/ilo_state_sol.c index dbc4b894f6a..38c0b719ab3 100644 --- a/src/gallium/drivers/ilo/core/ilo_state_sol.c +++ b/src/gallium/drivers/ilo/core/ilo_state_sol.c @@ -26,6 +26,7 @@ */ #include "ilo_debug.h" +#include "ilo_buffer.h" #include "ilo_state_sol.h" static bool @@ -134,7 +135,7 @@ sol_validate_gen7(const struct ilo_dev *dev, } static bool -sol_set_gen7_3DSTATE_STREAMOUT(struct ilo_state_sol *so, +sol_set_gen7_3DSTATE_STREAMOUT(struct ilo_state_sol *sol, const struct ilo_dev *dev, const struct ilo_state_sol_info *info) { @@ -176,12 +177,10 @@ sol_set_gen7_3DSTATE_STREAMOUT(struct ilo_state_sol *so, dw1 |= GEN7_SO_DW1_STATISTICS; if (ilo_dev_gen(dev) < ILO_GEN(8)) { - const uint8_t buffer_enables = - ((bool) info->buffer_strides[3]) << 3 | - ((bool) info->buffer_strides[2]) << 2 | - ((bool) info->buffer_strides[1]) << 1 | - ((bool) info->buffer_strides[0]); - + const uint8_t buffer_enables = ((bool) info->buffer_strides[3]) << 3 | + ((bool) info->buffer_strides[2]) << 2 | + ((bool) info->buffer_strides[1]) << 1 | + ((bool) info->buffer_strides[0]); dw1 |= buffer_enables << GEN7_SO_DW1_BUFFER_ENABLES__SHIFT; } @@ -194,27 +193,17 @@ sol_set_gen7_3DSTATE_STREAMOUT(struct ilo_state_sol *so, vue_read[0].offset << GEN7_SO_DW2_STREAM0_READ_OFFSET__SHIFT | vue_read[0].len << GEN7_SO_DW2_STREAM0_READ_LEN__SHIFT; - STATIC_ASSERT(ARRAY_SIZE(so->so) >= 4); - so->so[0] = dw1; - so->so[1] = dw2; - - if (ilo_dev_gen(dev) >= ILO_GEN(8)) { - uint32_t dw3, dw4; - - dw3 = info->buffer_strides[1] << GEN8_SO_DW3_BUFFER1_PITCH__SHIFT | - info->buffer_strides[0] << GEN8_SO_DW3_BUFFER0_PITCH__SHIFT; - dw4 = info->buffer_strides[3] << GEN8_SO_DW4_BUFFER3_PITCH__SHIFT | - info->buffer_strides[2] << GEN8_SO_DW4_BUFFER2_PITCH__SHIFT; + STATIC_ASSERT(ARRAY_SIZE(sol->streamout) >= 2); + sol->streamout[0] = dw1; + sol->streamout[1] = dw2; - so->so[2] = dw3; - so->so[3] = dw4; - } + memcpy(sol->strides, info->buffer_strides, sizeof(sol->strides)); return true; } static bool -sol_set_gen7_3DSTATE_SO_DECL_LIST(struct ilo_state_sol *so, +sol_set_gen7_3DSTATE_SO_DECL_LIST(struct ilo_state_sol *sol, const struct ilo_dev *dev, const struct ilo_state_sol_info *info, uint8_t max_decl_count) @@ -264,25 +253,146 @@ sol_set_gen7_3DSTATE_SO_DECL_LIST(struct ilo_state_sol *so, decl_counts[1] << GEN7_SO_DECL_DW2_STREAM1_ENTRY_COUNT__SHIFT | decl_counts[0] << GEN7_SO_DECL_DW2_STREAM0_ENTRY_COUNT__SHIFT; - STATIC_ASSERT(ARRAY_SIZE(so->so) >= 6); - so->so[4] = dw1; - so->so[5] = dw2; + STATIC_ASSERT(ARRAY_SIZE(sol->so_decl) >= 2); + sol->so_decl[0] = dw1; + sol->so_decl[1] = dw2; - STATIC_ASSERT(ARRAY_SIZE(so->decl[0]) == 2); - memcpy(so->decl, decl_list, sizeof(so->decl[0]) * max_decl_count); - so->decl_count = max_decl_count; + STATIC_ASSERT(ARRAY_SIZE(sol->decl[0]) == 2); + memcpy(sol->decl, decl_list, sizeof(sol->decl[0]) * max_decl_count); + sol->decl_count = max_decl_count; + + return true; +} + +static bool +sol_buffer_validate_gen7(const struct ilo_dev *dev, + const struct ilo_state_sol_buffer_info *info) +{ + ILO_DEV_ASSERT(dev, 7, 8); + + if (info->buf) + assert(info->offset < info->buf->bo_size && info->size); + + /* + * From the Ivy Bridge PRM, volume 2 part 1, page 208: + * + * "(Surface Base Address) This field specifies the starting DWord + * address..." + */ + assert(info->offset % 4 == 0); + + /* Gen8+ only */ + if (info->write_offset_load || info->write_offset_save) + assert(ilo_dev_gen(dev) >= ILO_GEN(8)); + + /* + * From the Broadwell PRM, volume 2b, page 206: + * + * "This field (Stream Offset) specifies the Offset in stream output + * buffer to start at, or whether to append to the end of an existing + * buffer. The Offset must be DWORD aligned." + */ + if (info->write_offset_imm_enable) { + assert(info->write_offset_load); + assert(info->write_offset_imm % 4 == 0); + } + + return true; +} + +static uint32_t +sol_buffer_get_gen6_size(const struct ilo_dev *dev, + const struct ilo_state_sol_buffer_info *info) +{ + uint32_t size; + + ILO_DEV_ASSERT(dev, 6, 8); + + if (!info->buf) + return 0; + + size = (info->offset + info->size <= info->buf->bo_size) ? info->size : + info->buf->bo_size - info->offset; + + /* + * From the Ivy Bridge PRM, volume 2 part 1, page 208: + * + * "(Surface End Address) This field specifies the ending DWord + * address..." + */ + size &= ~3; + + return size; +} + +static bool +sol_buffer_set_gen7_3dstate_so_buffer(struct ilo_state_sol_buffer *sb, + const struct ilo_dev *dev, + const struct ilo_state_sol_buffer_info *info) +{ + const uint32_t size = sol_buffer_get_gen6_size(dev, info); + + ILO_DEV_ASSERT(dev, 7, 7.5); + + if (!sol_buffer_validate_gen7(dev, info)) + return false; + + STATIC_ASSERT(ARRAY_SIZE(sb->so_buf) >= 2); + sb->so_buf[0] = info->offset; + sb->so_buf[1] = (size) ? info->offset + size : 0; + + return true; +} + +static bool +sol_buffer_set_gen8_3dstate_so_buffer(struct ilo_state_sol_buffer *sb, + const struct ilo_dev *dev, + const struct ilo_state_sol_buffer_info *info) +{ + const uint32_t size = sol_buffer_get_gen6_size(dev, info); + uint32_t dw1; + + ILO_DEV_ASSERT(dev, 8, 8); + + if (!sol_buffer_validate_gen7(dev, info)) + return false; + + dw1 = 0; + + if (info->buf) + dw1 |= GEN8_SO_BUF_DW1_ENABLE; + if (info->write_offset_load) + dw1 |= GEN8_SO_BUF_DW1_OFFSET_WRITE_ENABLE; + if (info->write_offset_save) + dw1 |= GEN8_SO_BUF_DW1_OFFSET_ENABLE; + + STATIC_ASSERT(ARRAY_SIZE(sb->so_buf) >= 4); + sb->so_buf[0] = dw1; + sb->so_buf[1] = info->offset; + + /* + * From the Broadwell PRM, volume 2b, page 205: + * + * "This field (Surface Size) specifies the size of buffer in number + * DWords minus 1 of the buffer in Graphics Memory." + */ + sb->so_buf[2] = (size) ? size / 4 - 1 : 0; + + /* load from imm or sb->write_offset_bo */ + sb->so_buf[3] = (info->write_offset_imm_enable) ? + info->write_offset_imm : ~0u; return true; } bool -ilo_state_sol_init(struct ilo_state_sol *so, +ilo_state_sol_init(struct ilo_state_sol *sol, const struct ilo_dev *dev, const struct ilo_state_sol_info *info) { bool ret = true; - assert(ilo_is_zeroed(so, sizeof(*so))); + assert(ilo_is_zeroed(sol, sizeof(*sol))); assert(ilo_is_zeroed(info->data, info->data_size)); if (ilo_dev_gen(dev) >= ILO_GEN(7)) { @@ -295,10 +405,10 @@ ilo_state_sol_init(struct ilo_state_sol *so, } assert(ilo_state_sol_data_size(dev, max_decl_count) <= info->data_size); - so->decl = (uint32_t (*)[2]) info->data; + sol->decl = (uint32_t (*)[2]) info->data; - ret &= sol_set_gen7_3DSTATE_STREAMOUT(so, dev, info); - ret &= sol_set_gen7_3DSTATE_SO_DECL_LIST(so, dev, info, max_decl_count); + ret &= sol_set_gen7_3DSTATE_STREAMOUT(sol, dev, info); + ret &= sol_set_gen7_3DSTATE_SO_DECL_LIST(sol, dev, info, max_decl_count); } assert(ret); @@ -318,3 +428,37 @@ ilo_state_sol_init_disabled(struct ilo_state_sol *sol, return ilo_state_sol_init(sol, dev, &info); } + +bool +ilo_state_sol_buffer_init(struct ilo_state_sol_buffer *sb, + const struct ilo_dev *dev, + const struct ilo_state_sol_buffer_info *info) +{ + bool ret = true; + + assert(ilo_is_zeroed(sb, sizeof(*sb))); + + if (ilo_dev_gen(dev) >= ILO_GEN(8)) + ret &= sol_buffer_set_gen8_3dstate_so_buffer(sb, dev, info); + else + ret &= sol_buffer_set_gen7_3dstate_so_buffer(sb, dev, info); + + sb->need_bo = (info->size > 0); + sb->need_write_offset_bo = (info->write_offset_save || + (info->write_offset_load && !info->write_offset_imm_enable)); + + assert(ret); + + return ret; +} + +bool +ilo_state_sol_buffer_init_disabled(struct ilo_state_sol_buffer *sb, + const struct ilo_dev *dev) +{ + struct ilo_state_sol_buffer_info info; + + memset(&info, 0, sizeof(info)); + + return ilo_state_sol_buffer_init(sb, dev, &info); +} diff --git a/src/gallium/drivers/ilo/core/ilo_state_sol.h b/src/gallium/drivers/ilo/core/ilo_state_sol.h index c5c693e5e56..2513fcb4979 100644 --- a/src/gallium/drivers/ilo/core/ilo_state_sol.h +++ b/src/gallium/drivers/ilo/core/ilo_state_sol.h @@ -99,12 +99,43 @@ struct ilo_state_sol_info { }; struct ilo_state_sol { - uint32_t so[6]; + uint32_t streamout[2]; + uint16_t strides[4]; + uint32_t so_decl[2]; uint32_t (*decl)[2]; uint8_t decl_count; }; +struct ilo_buffer; + +struct ilo_state_sol_buffer_info { + const struct ilo_buffer *buf; + uint32_t offset; + uint32_t size; + + /* + * Gen8+ only. When enabled, require a write offset bo of at least + * (sizeof(uint32_t) * ILO_STATE_SOL_MAX_BUFFER_COUNT) bytes + */ + bool write_offset_load; + bool write_offset_save; + + bool write_offset_imm_enable; + uint32_t write_offset_imm; +}; + +struct ilo_state_sol_buffer { + uint32_t so_buf[4]; + + bool need_bo; + bool need_write_offset_bo; + + /* managed by users */ + struct intel_bo *bo; + struct intel_bo *write_offset_bo; +}; + static inline size_t ilo_state_sol_data_size(const struct ilo_dev *dev, uint8_t max_decl_count) { @@ -123,4 +154,13 @@ ilo_state_sol_init_disabled(struct ilo_state_sol *sol, const struct ilo_dev *dev, bool render_disable); +bool +ilo_state_sol_buffer_init(struct ilo_state_sol_buffer *sb, + const struct ilo_dev *dev, + const struct ilo_state_sol_buffer_info *info); + +bool +ilo_state_sol_buffer_init_disabled(struct ilo_state_sol_buffer *sb, + const struct ilo_dev *dev); + #endif /* ILO_STATE_SOL_H */ diff --git a/src/gallium/drivers/ilo/ilo_render_gen7.c b/src/gallium/drivers/ilo/ilo_render_gen7.c index e4d2bf064da..7d0e4c44829 100644 --- a/src/gallium/drivers/ilo/ilo_render_gen7.c +++ b/src/gallium/drivers/ilo/ilo_render_gen7.c @@ -431,19 +431,21 @@ gen7_draw_sol(struct ilo_render *r, /* 3DSTATE_SO_BUFFER */ if ((DIRTY(SO) || dirty_sh || r->batch_bo_changed) && vec->so.enabled) { - const struct pipe_stream_output_info *so_info; int i; - so_info = ilo_shader_get_kernel_so_info(shader); - - for (i = 0; i < vec->so.count; i++) { - const int stride = so_info->stride[i] * 4; /* in bytes */ - - gen7_3DSTATE_SO_BUFFER(r->builder, i, stride, vec->so.states[i]); + for (i = 0; i < ILO_STATE_SOL_MAX_BUFFER_COUNT; i++) { + const struct pipe_stream_output_target *target = + (i < vec->so.count && vec->so.states[i]) ? + vec->so.states[i] : NULL; + const struct ilo_state_sol_buffer *sb = (target) ? + &((const struct ilo_stream_output_target *) target)->sb : + &vec->so.dummy_sb; + + if (ilo_dev_gen(r->dev) >= ILO_GEN(8)) + gen8_3DSTATE_SO_BUFFER(r->builder, sol, sb, i); + else + gen7_3DSTATE_SO_BUFFER(r->builder, sol, sb, i); } - - for (; i < 4; i++) - gen7_disable_3DSTATE_SO_BUFFER(r->builder, i); } /* 3DSTATE_SO_DECL_LIST */ diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c index 966a6e0470c..62e31809fb7 100644 --- a/src/gallium/drivers/ilo/ilo_state.c +++ b/src/gallium/drivers/ilo/ilo_state.c @@ -1899,19 +1899,28 @@ ilo_create_stream_output_target(struct pipe_context *pipe, unsigned buffer_offset, unsigned buffer_size) { - struct pipe_stream_output_target *target; + const struct ilo_dev *dev = ilo_context(pipe)->dev; + struct ilo_stream_output_target *target; + struct ilo_state_sol_buffer_info info; - target = MALLOC_STRUCT(pipe_stream_output_target); + target = CALLOC_STRUCT(ilo_stream_output_target); assert(target); - pipe_reference_init(&target->reference, 1); - target->buffer = NULL; - pipe_resource_reference(&target->buffer, res); - target->context = pipe; - target->buffer_offset = buffer_offset; - target->buffer_size = buffer_size; + pipe_reference_init(&target->base.reference, 1); + pipe_resource_reference(&target->base.buffer, res); + target->base.context = pipe; + target->base.buffer_offset = buffer_offset; + target->base.buffer_size = buffer_size; + + memset(&info, 0, sizeof(info)); + info.buf = ilo_buffer(res); + info.offset = buffer_offset; + info.size = buffer_size; + + ilo_state_sol_buffer_init(&target->sb, dev, &info); + target->sb.bo = info.buf->bo; - return target; + return &target->base; } static void @@ -2338,6 +2347,8 @@ ilo_state_vector_init(const struct ilo_dev *dev, ilo_state_ds_init_disabled(&vec->disabled_ds, dev); ilo_state_gs_init_disabled(&vec->disabled_gs, dev); + ilo_state_sol_buffer_init_disabled(&vec->so.dummy_sb, dev); + ilo_state_surface_init_for_null(&vec->fb.null_rt, dev); ilo_state_zs_init_for_null(&vec->fb.null_zs, dev); @@ -2439,6 +2450,10 @@ ilo_state_vector_resource_renamed(struct ilo_state_vector *vec, for (i = 0; i < vec->so.count; i++) { if (vec->so.states[i]->buffer == res) { + struct ilo_stream_output_target *target = + (struct ilo_stream_output_target *) vec->so.states[i]; + + target->sb.bo = ilo_buffer(res)->bo; states |= ILO_DIRTY_SO; break; } diff --git a/src/gallium/drivers/ilo/ilo_state.h b/src/gallium/drivers/ilo/ilo_state.h index d990269171b..e4746d0969b 100644 --- a/src/gallium/drivers/ilo/ilo_state.h +++ b/src/gallium/drivers/ilo/ilo_state.h @@ -217,11 +217,19 @@ struct ilo_view_state { unsigned count; }; +struct ilo_stream_output_target { + struct pipe_stream_output_target base; + + struct ilo_state_sol_buffer sb; +}; + struct ilo_so_state { struct pipe_stream_output_target *states[ILO_MAX_SO_BUFFERS]; unsigned count; unsigned append_bitmask; + struct ilo_state_sol_buffer dummy_sb; + bool enabled; };