radeonsi: implement a fixed-function tessellation control shader and its state
authorMarek Olšák <marek.olsak@amd.com>
Sun, 17 May 2015 23:59:37 +0000 (01:59 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 22 Jul 2015 22:59:32 +0000 (00:59 +0200)
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
src/gallium/drivers/radeonsi/si_pipe.c
src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/drivers/radeonsi/si_state.c
src/gallium/drivers/radeonsi/si_state_shaders.c

index 8678fe6260b47bba56e663e86a5ed3736a05a911..b545a4f4a5f7cf601180e4312f4ab69684f40ff7 100644 (file)
@@ -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);
index 9e2ad1888010781f6a095cc50ad9e59797513edf..08eae960c06a5894cfb05eb784182daf4990914f 100644 (file)
@@ -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 {
index 316c689357b089ba0ce27a33a396738fa086977b..482e4fed5a0eefa51bc975b4b933aabab46c369a 100644 (file)
@@ -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;
index 686718e422133d93fb9eae2e232dfb43e3597f49..76d590b4e6c87954b56d8d41c47d358876c4c73a 100644 (file)
@@ -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);