From db267a04ceee51ca1698c3a68127508fa1e31c86 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Mon, 18 May 2015 01:59:37 +0200 Subject: [PATCH] radeonsi: implement a fixed-function tessellation control shader and its state MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reviewed-by: Michel Dänzer --- src/gallium/drivers/radeonsi/si_pipe.c | 2 + src/gallium/drivers/radeonsi/si_pipe.h | 1 + src/gallium/drivers/radeonsi/si_state.c | 25 +++++++++++ .../drivers/radeonsi/si_state_shaders.c | 41 ++++++++++++++++++- 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c index 8678fe6260b..b545a4f4a5f 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.c +++ b/src/gallium/drivers/radeonsi/si_pipe.c @@ -59,6 +59,8 @@ static void si_destroy_context(struct pipe_context *context) if (sctx->dummy_pixel_shader) { sctx->b.b.delete_fs_state(&sctx->b.b, sctx->dummy_pixel_shader); } + if (sctx->fixed_func_tcs_shader) + sctx->b.b.delete_tcs_state(&sctx->b.b, sctx->fixed_func_tcs_shader); sctx->b.b.delete_depth_stencil_alpha_state(&sctx->b.b, sctx->custom_dsa_flush); sctx->b.b.delete_blend_state(&sctx->b.b, sctx->custom_blend_resolve); sctx->b.b.delete_blend_state(&sctx->b.b, sctx->custom_blend_decompress); diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h index 9e2ad188801..08eae960c06 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -136,6 +136,7 @@ struct si_context { struct si_screen *screen; struct si_pm4_state *init_config; struct pipe_fence_handle *last_gfx_fence; + struct si_shader_selector *fixed_func_tcs_shader; union { struct { diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 316c689357b..482e4fed5a0 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -2895,6 +2895,30 @@ static void si_set_polygon_stipple(struct pipe_context *ctx, } } +static void si_set_tess_state(struct pipe_context *ctx, + const float default_outer_level[4], + const float default_inner_level[2]) +{ + struct si_context *sctx = (struct si_context *)ctx; + struct pipe_constant_buffer cb; + float array[8]; + + memcpy(array, default_outer_level, sizeof(float) * 4); + memcpy(array+4, default_inner_level, sizeof(float) * 2); + + cb.buffer = NULL; + cb.user_buffer = NULL; + cb.buffer_size = sizeof(array); + + si_upload_const_buffer(sctx, (struct r600_resource**)&cb.buffer, + (void*)array, sizeof(array), + &cb.buffer_offset); + + ctx->set_constant_buffer(ctx, PIPE_SHADER_TESS_CTRL, + SI_DRIVER_STATE_CONST_BUF, &cb); + pipe_resource_reference(&cb.buffer, NULL); +} + static void si_texture_barrier(struct pipe_context *ctx) { struct si_context *sctx = (struct si_context *)ctx; @@ -2972,6 +2996,7 @@ void si_init_state_functions(struct si_context *sctx) sctx->b.b.texture_barrier = si_texture_barrier; sctx->b.b.set_polygon_stipple = si_set_polygon_stipple; sctx->b.b.set_min_samples = si_set_min_samples; + sctx->b.b.set_tess_state = si_set_tess_state; sctx->b.set_occlusion_query_state = si_set_occlusion_query_state; sctx->b.need_gfx_cs_space = si_need_gfx_cs_space; diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c index 686718e4221..76d590b4e6c 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.c +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c @@ -30,6 +30,7 @@ #include "sid.h" #include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_ureg.h" #include "util/u_memory.h" #include "util/u_simple_shaders.h" @@ -1149,6 +1150,40 @@ static void si_init_tess_factor_ring(struct si_context *sctx) sctx->b.flags |= SI_CONTEXT_VGT_FLUSH; } +/** + * This is used when TCS is NULL in the VS->TCS->TES chain. In this case, + * VS passes its outputs to TES directly, so the fixed-function shader only + * has to write TESSOUTER and TESSINNER. + */ +static void si_generate_fixed_func_tcs(struct si_context *sctx) +{ + struct ureg_src const0, const1; + struct ureg_dst tessouter, tessinner; + struct ureg_program *ureg = ureg_create(TGSI_PROCESSOR_TESS_CTRL); + + if (!ureg) + return; /* if we get here, we're screwed */ + + assert(!sctx->fixed_func_tcs_shader); + + ureg_DECL_constant2D(ureg, 0, 1, SI_DRIVER_STATE_CONST_BUF); + const0 = ureg_src_dimension(ureg_src_register(TGSI_FILE_CONSTANT, 0), + SI_DRIVER_STATE_CONST_BUF); + const1 = ureg_src_dimension(ureg_src_register(TGSI_FILE_CONSTANT, 1), + SI_DRIVER_STATE_CONST_BUF); + + tessouter = ureg_DECL_output(ureg, TGSI_SEMANTIC_TESSOUTER, 0); + tessinner = ureg_DECL_output(ureg, TGSI_SEMANTIC_TESSINNER, 0); + + ureg_MOV(ureg, tessouter, const0); + ureg_MOV(ureg, tessinner, const1); + ureg_END(ureg); + + sctx->fixed_func_tcs_shader = + ureg_create_shader_and_destroy(ureg, &sctx->b.b); + assert(sctx->fixed_func_tcs_shader); +} + static void si_update_vgt_shader_config(struct si_context *sctx) { /* Calculate the index of the config. @@ -1202,7 +1237,11 @@ void si_update_shaders(struct si_context *sctx) si_shader_select(ctx, sctx->tcs_shader); si_pm4_bind_state(sctx, hs, sctx->tcs_shader->current->pm4); } else { - assert(!"generate TCS shader"); + if (!sctx->fixed_func_tcs_shader) + si_generate_fixed_func_tcs(sctx); + si_shader_select(ctx, sctx->fixed_func_tcs_shader); + si_pm4_bind_state(sctx, hs, + sctx->fixed_func_tcs_shader->current->pm4); } si_shader_select(ctx, sctx->tes_shader); -- 2.30.2