From 54e23442e24e72caa40a463763c21d2c439e8c35 Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Fri, 21 Sep 2018 12:22:34 -0700 Subject: [PATCH] iris: Add support for TCS passthrough If no TCS is provided, create a "passthrough" TCS that will take the default values set in the API as constants and pass to the TES, along with any other inputs it expects. The code to create the NIR shader is the same as in i965. Tested with ./piglit run -t 'tess' quick_shader r and fixed a dozen crashes from that list. --- src/gallium/drivers/iris/iris_context.h | 3 ++ src/gallium/drivers/iris/iris_program.c | 51 +++++++++++--------- src/gallium/drivers/iris/iris_state.c | 62 ++++++++++++++++++++++++- 3 files changed, 93 insertions(+), 23 deletions(-) diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index 9f847136937..48ebeb63ec2 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -357,6 +357,9 @@ struct iris_context { struct pipe_stencil_ref stencil_ref; struct pipe_framebuffer_state framebuffer; + float default_outer_level[4]; + float default_inner_level[2]; + bool primitive_restart; unsigned cut_index; enum pipe_prim_type prim_mode:8; diff --git a/src/gallium/drivers/iris/iris_program.c b/src/gallium/drivers/iris/iris_program.c index ab2ce815961..8c425c46d17 100644 --- a/src/gallium/drivers/iris/iris_program.c +++ b/src/gallium/drivers/iris/iris_program.c @@ -491,6 +491,8 @@ iris_compile_tcs(struct iris_context *ice, { struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen; const struct brw_compiler *compiler = screen->compiler; + const struct nir_shader_compiler_options *options = + compiler->glsl_compiler_options[MESA_SHADER_TESS_CTRL].NirOptions; const struct gen_device_info *devinfo = &screen->devinfo; void *mem_ctx = ralloc_context(NULL); struct brw_tcs_prog_data *tcs_prog_data = @@ -498,11 +500,21 @@ iris_compile_tcs(struct iris_context *ice, struct brw_vue_prog_data *vue_prog_data = &tcs_prog_data->base; struct brw_stage_prog_data *prog_data = &vue_prog_data->base; - nir_shader *nir = ish->nir; + nir_shader *nir; - assign_common_binding_table_offsets(devinfo, nir, prog_data, 0); + if (ish) { + nir = ish->nir; - iris_setup_uniforms(compiler, mem_ctx, nir, prog_data); + assign_common_binding_table_offsets(devinfo, nir, prog_data, 0); + iris_setup_uniforms(compiler, mem_ctx, nir, prog_data); + } else { + nir = brw_nir_create_passthrough_tcs(mem_ctx, compiler, options, key); + + /* Reserve space for passing the default tess levels as constants. */ + prog_data->param = rzalloc_array(mem_ctx, uint32_t, 8); + prog_data->nr_params = 8; + prog_data->ubo_ranges[0].length = 1; + } char *error_str = NULL; const unsigned *program = @@ -533,21 +545,13 @@ iris_update_compiled_tcs(struct iris_context *ice) { struct iris_uncompiled_shader *tcs = ice->shaders.uncompiled[MESA_SHADER_TESS_CTRL]; - struct iris_uncompiled_shader *tes = - ice->shaders.uncompiled[MESA_SHADER_TESS_EVAL]; - - assert(!(tes && !tcs)); - - if (!tcs) { - iris_unbind_shader(ice, IRIS_CACHE_TCS); - return; - } const struct shader_info *tes_info = iris_get_shader_info(ice, MESA_SHADER_TESS_EVAL); struct brw_tcs_prog_key key = { - .program_string_id = tcs->program_id, + .program_string_id = tcs ? tcs->program_id : get_new_program_id((void *)ice->ctx.screen), .tes_primitive_mode = tes_info->tess.primitive_mode, + .input_vertices = ice->state.vertices_per_patch, }; get_unified_tess_slots(ice, &key.outputs_written, &key.patch_outputs_written); @@ -620,11 +624,6 @@ iris_update_compiled_tes(struct iris_context *ice) struct iris_uncompiled_shader *ish = ice->shaders.uncompiled[MESA_SHADER_TESS_EVAL]; - if (!ish) { - iris_unbind_shader(ice, IRIS_CACHE_TES); - return; - } - struct brw_tes_prog_key key = { .program_string_id = ish->program_id }; get_unified_tess_slots(ice, &key.inputs_read, &key.patch_inputs_read); ice->vtbl.populate_tes_key(ice, &key); @@ -861,12 +860,20 @@ iris_update_compiled_shaders(struct iris_context *ice) old_prog_datas[i] = get_vue_prog_data(ice, i); } + if (dirty & (IRIS_DIRTY_UNCOMPILED_TCS | IRIS_DIRTY_UNCOMPILED_TES)) { + struct iris_uncompiled_shader *tes = + ice->shaders.uncompiled[MESA_SHADER_TESS_EVAL]; + if (tes) { + iris_update_compiled_tcs(ice); + iris_update_compiled_tes(ice); + } else { + iris_unbind_shader(ice, IRIS_CACHE_TCS); + iris_unbind_shader(ice, IRIS_CACHE_TES); + } + } + if (dirty & IRIS_DIRTY_UNCOMPILED_VS) iris_update_compiled_vs(ice); - if (dirty & IRIS_DIRTY_UNCOMPILED_TCS) - iris_update_compiled_tcs(ice); - if (dirty & IRIS_DIRTY_UNCOMPILED_TES) - iris_update_compiled_tes(ice); if (dirty & IRIS_DIRTY_UNCOMPILED_GS) iris_update_compiled_gs(ice); diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index 0abd0fd2f02..0485a8aa2fd 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -1510,6 +1510,22 @@ iris_set_sampler_views(struct pipe_context *ctx, ice->state.dirty |= (IRIS_DIRTY_BINDINGS_VS << stage); } +/** + * The pipe->set_tess_state() driver hook. + */ +static void +iris_set_tess_state(struct pipe_context *ctx, + const float default_outer_level[4], + const float default_inner_level[2]) +{ + struct iris_context *ice = (struct iris_context *) ctx; + + memcpy(&ice->state.default_outer_level[0], &default_outer_level[0], 4 * sizeof(float)); + memcpy(&ice->state.default_inner_level[0], &default_inner_level[0], 2 * sizeof(float)); + + ice->state.dirty |= IRIS_DIRTY_CONSTANTS_TCS; +} + static void iris_surface_destroy(struct pipe_context *ctx, struct pipe_surface *p_surf) { @@ -3157,7 +3173,6 @@ iris_populate_binding_table(struct iris_context *ice, if (!shader) return; - const struct shader_info *info = iris_get_shader_info(ice, stage); struct iris_shader_state *shs = &ice->state.shaders[stage]; uint32_t binder_addr = binder->bo->gtt_offset; @@ -3165,6 +3180,13 @@ iris_populate_binding_table(struct iris_context *ice, uint32_t *bt_map = binder->map + binder->bt_offset[stage]; int s = 0; + const struct shader_info *info = iris_get_shader_info(ice, stage); + if (!info) { + /* TCS passthrough doesn't need a binding table. */ + assert(stage == MESA_SHADER_TESS_CTRL); + return; + } + if (stage == MESA_SHADER_FRAGMENT) { struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer; /* Note that cso_fb->nr_cbufs == fs_key->nr_color_regions. */ @@ -3495,6 +3517,43 @@ iris_upload_dirty_render_state(struct iris_context *ice, } } + /* Upload constants for TCS passthrough. */ + if ((dirty & IRIS_DIRTY_CONSTANTS_TCS) && + ice->shaders.prog[MESA_SHADER_TESS_CTRL] && + !ice->shaders.uncompiled[MESA_SHADER_TESS_CTRL]) { + struct iris_compiled_shader *tes_shader = ice->shaders.prog[MESA_SHADER_TESS_EVAL]; + assert(tes_shader); + + /* Passthrough always copies 2 vec4s, so when uploading data we ensure + * it is in the right layout for TES. + */ + float hdr[8] = {}; + struct brw_tes_prog_data *tes_prog_data = (void *) tes_shader->prog_data; + switch (tes_prog_data->domain) { + case BRW_TESS_DOMAIN_QUAD: + for (int i = 0; i < 4; i++) + hdr[7 - i] = ice->state.default_outer_level[i]; + hdr[3] = ice->state.default_inner_level[0]; + hdr[2] = ice->state.default_inner_level[1]; + break; + case BRW_TESS_DOMAIN_TRI: + for (int i = 0; i < 3; i++) + hdr[7 - i] = ice->state.default_outer_level[i]; + hdr[4] = ice->state.default_inner_level[0]; + break; + case BRW_TESS_DOMAIN_ISOLINE: + hdr[7] = ice->state.default_outer_level[1]; + hdr[6] = ice->state.default_outer_level[0]; + break; + } + + struct iris_shader_state *shs = &ice->state.shaders[MESA_SHADER_TESS_CTRL]; + struct iris_const_buffer *cbuf = &shs->constbuf[0]; + u_upload_data(ice->ctx.const_uploader, 0, sizeof(hdr), 32, + &hdr[0], &cbuf->data.offset, + &cbuf->data.res); + } + for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) { if (!(dirty & (IRIS_DIRTY_CONSTANTS_VS << stage))) continue; @@ -4415,6 +4474,7 @@ genX(init_state)(struct iris_context *ice) ctx->set_constant_buffer = iris_set_constant_buffer; ctx->set_shader_buffers = iris_set_shader_buffers; ctx->set_sampler_views = iris_set_sampler_views; + ctx->set_tess_state = iris_set_tess_state; ctx->set_framebuffer_state = iris_set_framebuffer_state; ctx->set_polygon_stipple = iris_set_polygon_stipple; ctx->set_sample_mask = iris_set_sample_mask; -- 2.30.2