ilo: add ilo_state_sol_buffer

It serves the same purpose as ilo_state_vertex_buffer does.
This commit is contained in:
Chia-I Wu 2015-06-15 15:17:45 +08:00
parent 9904e647cc
commit e3372c4bfb
6 changed files with 315 additions and 101 deletions

View File

@ -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);
ILO_DEV_ASSERT(builder->dev, 7, 7.5);
buf = ilo_buffer(so_target->buffer);
/* DWord-aligned */
assert(stride % 4 == 0);
assert(so_target->buffer_offset % 4 == 0);
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;
/* 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 (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);
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 (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
dw[4] = 0;
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;
}
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

View File

@ -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;
STATIC_ASSERT(ARRAY_SIZE(sol->streamout) >= 2);
sol->streamout[0] = dw1;
sol->streamout[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;
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);
}

View File

@ -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 */

View File

@ -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 < 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;
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]);
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 */

View File

@ -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;
return target;
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->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;
}

View File

@ -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;
};