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;