From 9ea05ccf1f20691cde6911762bce8207c7283714 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 6 Jun 2018 11:59:17 -0700 Subject: [PATCH] iris: completely rewrite binder now we get a new one per batch, and flush if it fills up --- src/gallium/drivers/iris/iris_batch.c | 6 ++ src/gallium/drivers/iris/iris_batch.h | 5 +- src/gallium/drivers/iris/iris_binder.c | 64 +++++++++++--- src/gallium/drivers/iris/iris_binder.h | 18 +++- src/gallium/drivers/iris/iris_blorp.c | 6 +- src/gallium/drivers/iris/iris_context.c | 3 - src/gallium/drivers/iris/iris_context.h | 2 - src/gallium/drivers/iris/iris_draw.c | 2 +- src/gallium/drivers/iris/iris_state.c | 106 +++++++++++++----------- 9 files changed, 136 insertions(+), 76 deletions(-) diff --git a/src/gallium/drivers/iris/iris_batch.c b/src/gallium/drivers/iris/iris_batch.c index 6ee46030893..c3078d9c638 100644 --- a/src/gallium/drivers/iris/iris_batch.c +++ b/src/gallium/drivers/iris/iris_batch.c @@ -23,6 +23,7 @@ */ #include "iris_batch.h" +#include "iris_binder.h" #include "iris_bufmgr.h" #include "iris_context.h" @@ -128,6 +129,8 @@ iris_init_batch(struct iris_batch *batch, batch->validation_list = malloc(batch->exec_array_size * sizeof(batch->validation_list[0])); + batch->binder.bo = NULL; + batch->cache.render = _mesa_hash_table_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); batch->cache.depth = _mesa_set_create(NULL, _mesa_hash_pointer, @@ -221,6 +224,9 @@ iris_batch_reset(struct iris_batch *batch) create_batch(batch); assert(batch->bo->index == 0); + iris_destroy_binder(&batch->binder); + iris_init_binder(&batch->binder, batch->bo->bufmgr); + if (batch->state_sizes) _mesa_hash_table_clear(batch->state_sizes, NULL); diff --git a/src/gallium/drivers/iris/iris_batch.h b/src/gallium/drivers/iris/iris_batch.h index 13525a4d4dd..88a58d083f5 100644 --- a/src/gallium/drivers/iris/iris_batch.h +++ b/src/gallium/drivers/iris/iris_batch.h @@ -28,6 +28,7 @@ #include #include "i915_drm.h" #include "common/gen_decoder.h" +#include "iris_binder.h" /* The kernel assumes batchbuffers are smaller than 256kB. */ #define MAX_BATCH_SIZE (256 * 1024) @@ -50,7 +51,6 @@ struct iris_batch { /** Size of the primary batch if we've moved on to a secondary. */ unsigned primary_batch_size; - /** Last BO submitted to the hardware. Used for glFinish(). */ struct iris_bo *last_bo; @@ -68,6 +68,9 @@ struct iris_batch { /** The amount of aperture space (in bytes) used by all exec_bos */ int aperture_space; + /** Binder (containing binding tables) */ + struct iris_binder binder; + struct { /** * Set of struct brw_bo * that have been rendered to within this diff --git a/src/gallium/drivers/iris/iris_binder.c b/src/gallium/drivers/iris/iris_binder.c index 408e2007ae2..1b1c78380bb 100644 --- a/src/gallium/drivers/iris/iris_binder.c +++ b/src/gallium/drivers/iris/iris_binder.c @@ -25,27 +25,69 @@ #include "util/u_math.h" #include "iris_binder.h" #include "iris_bufmgr.h" +#include "iris_context.h" /* 64kb */ #define BINDER_SIZE (64 * 1024) -void * -iris_binder_reserve(struct iris_binder *binder, unsigned size, - uint32_t *out_offset) +/** + * Reserve a block of space in the binder. + */ +uint32_t +iris_binder_reserve(struct iris_batch *batch, unsigned size) { - /* XXX: if we ever make this allocate a new BO, then make binder_reserve - * return the BO, so at least verify use_pinned_bo gets the right one - */ - /* XXX: Implement a real ringbuffer, for now just croak if run out */ - assert(size > 0); - assert(binder->insert_point + size <= BINDER_SIZE); + struct iris_binder *binder = &batch->binder; + assert(size > 0); assert((binder->insert_point % 64) == 0); - *out_offset = binder->insert_point; + + /* If we can't fit all stages in the binder, flush the batch which + * will cause us to gain a new empty binder. + */ + if (binder->insert_point + size > BINDER_SIZE) + iris_batch_flush(batch); + + uint32_t offset = binder->insert_point; + + /* It had better fit now. */ + assert(offset + size <= BINDER_SIZE); binder->insert_point = align(binder->insert_point + size, 64); - return binder->map + *out_offset; + iris_use_pinned_bo(batch, binder->bo, false); + + return offset; +} + +/** + * Reserve and record binder space for 3D pipeline shader stages. + */ +void +iris_binder_reserve_3d(struct iris_batch *batch, + struct iris_compiled_shader **shaders) +{ + struct iris_binder *binder = &batch->binder; + unsigned total_size = 0; + unsigned sizes[MESA_SHADER_STAGES] = {}; + + for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) { + if (!shaders[stage]) + continue; + + const struct brw_stage_prog_data *prog_data = + (const void *) shaders[stage]->prog_data; + + sizes[stage] = align(prog_data->binding_table.size_bytes, 64); + total_size += sizes[stage]; + } + + uint32_t offset = iris_binder_reserve(batch, total_size); + + /* Assign space and record the current binding table. */ + for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) { + binder->bt_offset[stage] = sizes[stage] > 0 ? offset : 0; + offset += sizes[stage]; + } } void diff --git a/src/gallium/drivers/iris/iris_binder.h b/src/gallium/drivers/iris/iris_binder.h index 5830288b5c5..ea455dd5cfd 100644 --- a/src/gallium/drivers/iris/iris_binder.h +++ b/src/gallium/drivers/iris/iris_binder.h @@ -26,22 +26,32 @@ #include #include +#include "compiler/shader_enums.h" struct iris_bo; +struct iris_batch; struct iris_bufmgr; +struct iris_compiled_shader; struct iris_binder { struct iris_bo *bo; void *map; - /* Insert new entries at this offset (in bytes) */ - unsigned insert_point; + /** Insert new entries at this offset (in bytes) */ + uint32_t insert_point; + + /** + * Last assigned offset for each shader stage's binding table. + * Zero is considered invalid and means there's no binding table. + */ + uint32_t bt_offset[MESA_SHADER_STAGES]; }; void iris_init_binder(struct iris_binder *binder, struct iris_bufmgr *bufmgr); void iris_destroy_binder(struct iris_binder *binder); -void *iris_binder_reserve(struct iris_binder *binder, unsigned size, - uint32_t *out_offset); +uint32_t iris_binder_reserve(struct iris_batch *batch, unsigned size); +void iris_binder_reserve_3d(struct iris_batch *batch, + struct iris_compiled_shader **shaders); #endif diff --git a/src/gallium/drivers/iris/iris_blorp.c b/src/gallium/drivers/iris/iris_blorp.c index 06ba830de75..8def4619e8c 100644 --- a/src/gallium/drivers/iris/iris_blorp.c +++ b/src/gallium/drivers/iris/iris_blorp.c @@ -134,10 +134,8 @@ blorp_alloc_binding_table(struct blorp_batch *blorp_batch, struct iris_context *ice = blorp_batch->blorp->driver_ctx; struct iris_batch *batch = blorp_batch->driver_batch; - uint32_t *bt_map = iris_binder_reserve(&ice->state.binder, - num_entries * sizeof(uint32_t), - bt_offset); - iris_use_pinned_bo(batch, ice->state.binder.bo, false); + *bt_offset = iris_binder_reserve(batch, num_entries * sizeof(uint32_t)); + uint32_t *bt_map = batch->binder.map + *bt_offset; for (unsigned i = 0; i < num_entries; i++) { surface_maps[i] = stream_state(batch, ice->state.surface_uploader, diff --git a/src/gallium/drivers/iris/iris_context.c b/src/gallium/drivers/iris/iris_context.c index 417a09f64ee..09eb288bbbc 100644 --- a/src/gallium/drivers/iris/iris_context.c +++ b/src/gallium/drivers/iris/iris_context.c @@ -80,7 +80,6 @@ iris_destroy_context(struct pipe_context *ctx) u_upload_destroy(ctx->stream_uploader); iris_destroy_program_cache(ice); - iris_destroy_binder(&ice->state.binder); u_upload_destroy(ice->state.surface_uploader); u_upload_destroy(ice->state.dynamic_uploader); @@ -137,8 +136,6 @@ iris_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags) iris_init_program_cache(ice); - iris_init_binder(&ice->state.binder, screen->bufmgr); - ice->state.surface_uploader = u_upload_create(&ice->ctx, 16384, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, IRIS_RESOURCE_FLAG_SURFACE_MEMZONE); diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index f23ba7c73e8..90230e8705a 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -30,7 +30,6 @@ #include "intel/common/gen_debug.h" #include "intel/compiler/brw_compiler.h" #include "iris_batch.h" -#include "iris_binder.h" #include "iris_screen.h" struct iris_bo; @@ -256,7 +255,6 @@ struct iris_context { unsigned num_samplers[MESA_SHADER_STAGES]; unsigned num_textures[MESA_SHADER_STAGES]; - struct iris_binder binder; struct u_upload_mgr *surface_uploader; // XXX: may want a separate uploader for "hey I made a CSO!" vs // "I'm streaming this out at draw time and never want it again!" diff --git a/src/gallium/drivers/iris/iris_draw.c b/src/gallium/drivers/iris/iris_draw.c index 2494ade77d1..5295f2ac847 100644 --- a/src/gallium/drivers/iris/iris_draw.c +++ b/src/gallium/drivers/iris/iris_draw.c @@ -52,8 +52,8 @@ iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) iris_cache_sets_clear(batch); // XXX: ^^^ - iris_update_compiled_shaders(ice); + iris_binder_reserve_3d(batch, ice->shaders.prog); ice->vtbl.upload_render_state(ice, batch, info); // XXX: don't flush always diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index f8772315d1c..e0000c19887 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -2092,6 +2092,54 @@ use_sampler_view(struct iris_batch *batch, struct iris_sampler_view *isv) return isv->surface_state_offset; } +static void +iris_populate_binding_table(struct iris_context *ice, + struct iris_batch *batch, + gl_shader_stage stage) +{ + const struct iris_binder *binder = &batch->binder; + struct iris_compiled_shader *shader = ice->shaders.prog[stage]; + if (!shader) + return; + + // Surfaces: + // - pull constants + // - ubos/ssbos/abos + // - images + // - textures + // - render targets - write and read + + struct brw_stage_prog_data *prog_data = (void *) shader->prog_data; + uint32_t *bt_map = binder->map + binder->bt_offset[stage]; + int s = 0; + + if (stage == MESA_SHADER_FRAGMENT) { + struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer; + for (unsigned i = 0; i < cso_fb->nr_cbufs; i++) { + bt_map[s++] = use_surface(batch, cso_fb->cbufs[i], true); + } + } + + assert(prog_data->binding_table.texture_start == + (ice->state.num_textures[stage] ? s : 0xd0d0d0d0)); + + for (int i = 0; i < ice->state.num_textures[stage]; i++) { + struct iris_sampler_view *view = ice->state.textures[stage][i]; + bt_map[s++] = use_sampler_view(batch, view); + } + +#if 0 + // XXX: not implemented yet + assert(prog_data->binding_table.pull_constants_start == 0xd0d0d0d0); + assert(prog_data->binding_table.ubo_start == 0xd0d0d0d0); + assert(prog_data->binding_table.ssbo_start == 0xd0d0d0d0); + assert(prog_data->binding_table.image_start == 0xd0d0d0d0); + assert(prog_data->binding_table.shader_time_start == 0xd0d0d0d0); + //assert(prog_data->binding_table.plane_start[1] == 0xd0d0d0d0); + //assert(prog_data->binding_table.plane_start[2] == 0xd0d0d0d0); +#endif +} + static void iris_upload_render_state(struct iris_context *ice, struct iris_batch *batch, @@ -2226,61 +2274,19 @@ iris_upload_render_state(struct iris_context *ice, } } - // Surfaces: - // - pull constants - // - ubos/ssbos/abos - // - images - // - textures - // - render targets - write and read - // XXX: 3DSTATE_BINDING_TABLE_POINTERS_XS - - for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) { - struct iris_compiled_shader *shader = ice->shaders.prog[stage]; - if (!shader) // XXX: dirty bits...also, emit a disable maybe? - continue; - - struct brw_stage_prog_data *prog_data = (void *) shader->prog_data; - uint32_t bt_offset = 0; - uint32_t *bt_map = NULL; - int s = 0; - - if (prog_data->binding_table.size_bytes != 0) { - iris_use_pinned_bo(batch, ice->state.binder.bo, false); - bt_map = iris_binder_reserve(&ice->state.binder, - prog_data->binding_table.size_bytes, - &bt_offset); - } + if (1) { // XXX: DIRTY BINDINGS + const struct iris_binder *binder = &batch->binder; - iris_emit_cmd(batch, GENX(3DSTATE_BINDING_TABLE_POINTERS_VS), ptr) { - ptr._3DCommandSubOpcode = 38 + stage; - ptr.PointertoVSBindingTable = bt_offset; - } - - if (stage == MESA_SHADER_FRAGMENT) { - struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer; - for (unsigned i = 0; i < cso_fb->nr_cbufs; i++) { - bt_map[s++] = use_surface(batch, cso_fb->cbufs[i], true); + for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) { + iris_emit_cmd(batch, GENX(3DSTATE_BINDING_TABLE_POINTERS_VS), ptr) { + ptr._3DCommandSubOpcode = 38 + stage; + ptr.PointertoVSBindingTable = binder->bt_offset[stage]; } } - assert(prog_data->binding_table.texture_start == - (ice->state.num_textures[stage] ? s : 0xd0d0d0d0)); - - for (int i = 0; i < ice->state.num_textures[stage]; i++) { - struct iris_sampler_view *view = ice->state.textures[stage][i]; - bt_map[s++] = use_sampler_view(batch, view); + for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) { + iris_populate_binding_table(ice, batch, stage); } - -#if 0 - // XXX: not implemented yet - assert(prog_data->binding_table.pull_constants_start == 0xd0d0d0d0); - assert(prog_data->binding_table.ubo_start == 0xd0d0d0d0); - assert(prog_data->binding_table.ssbo_start == 0xd0d0d0d0); - assert(prog_data->binding_table.image_start == 0xd0d0d0d0); - assert(prog_data->binding_table.shader_time_start == 0xd0d0d0d0); - //assert(prog_data->binding_table.plane_start[1] == 0xd0d0d0d0); - //assert(prog_data->binding_table.plane_start[2] == 0xd0d0d0d0); -#endif } for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) { -- 2.30.2