radeonsi: implement SAMPLEPOS fragment shader input
authorMarek Olšák <marek.olsak@amd.com>
Tue, 6 May 2014 16:20:58 +0000 (18:20 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Mon, 2 Jun 2014 10:58:22 +0000 (12:58 +0200)
The sample positions are read from a constant buffer.

src/gallium/drivers/radeon/cayman_msaa.c
src/gallium/drivers/radeon/r600_pipe_common.c
src/gallium/drivers/radeon/r600_pipe_common.h
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_state.c

index 8727f3e235947d67bff23a87b3b8a39aee90edd0..47fc5c497f1a03473ce79bea598339646fd42773 100644 (file)
@@ -123,6 +123,23 @@ void cayman_get_sample_position(struct pipe_context *ctx, unsigned sample_count,
        }
 }
 
+void cayman_init_msaa(struct pipe_context *ctx)
+{
+       struct r600_common_context *rctx = (struct r600_common_context*)ctx;
+       int i;
+
+       cayman_get_sample_position(ctx, 1, 0, rctx->sample_locations_1x[0]);
+
+       for (i = 0; i < 2; i++)
+               cayman_get_sample_position(ctx, 2, i, rctx->sample_locations_2x[i]);
+       for (i = 0; i < 4; i++)
+               cayman_get_sample_position(ctx, 4, i, rctx->sample_locations_4x[i]);
+       for (i = 0; i < 8; i++)
+               cayman_get_sample_position(ctx, 8, i, rctx->sample_locations_8x[i]);
+       for (i = 0; i < 16; i++)
+               cayman_get_sample_position(ctx, 16, i, rctx->sample_locations_16x[i]);
+}
+
 void cayman_emit_msaa_sample_locs(struct radeon_winsys_cs *cs, int nr_samples)
 {
        switch (nr_samples) {
index 70c4d1adefba783b553af0e6ff1dfc60b7fd3e9f..4c6cf0e60c1ad7c691cbd958a874df8d74355cbe 100644 (file)
@@ -154,6 +154,7 @@ bool r600_common_context_init(struct r600_common_context *rctx,
        r600_init_context_texture_functions(rctx);
        r600_streamout_init(rctx);
        r600_query_init(rctx);
+       cayman_init_msaa(&rctx->b);
 
        rctx->allocator_so_filled_size = u_suballocator_create(&rctx->b, 4096, 4,
                                                               0, PIPE_USAGE_DEFAULT, TRUE);
index b7e4e65cf110a2f7c681f2fd0576286f135fea0c..d82adf5d387cb7e0160213d9dec5f92744f2742c 100644 (file)
@@ -357,6 +357,15 @@ struct r600_common_context {
        boolean                         saved_render_cond_cond;
        unsigned                        saved_render_cond_mode;
 
+       /* MSAA sample locations.
+        * The first index is the sample index.
+        * The second index is the coordinate: X, Y. */
+       float                           sample_locations_1x[1][2];
+       float                           sample_locations_2x[2][2];
+       float                           sample_locations_4x[4][2];
+       float                           sample_locations_8x[8][2];
+       float                           sample_locations_16x[16][2];
+
        /* Copy one resource to another using async DMA. */
        void (*dma_copy)(struct pipe_context *ctx,
                         struct pipe_resource *dst,
@@ -472,6 +481,7 @@ extern const uint32_t eg_sample_locs_4x[4];
 extern const unsigned eg_max_dist_4x;
 void cayman_get_sample_position(struct pipe_context *ctx, unsigned sample_count,
                                unsigned sample_index, float *out_value);
+void cayman_init_msaa(struct pipe_context *ctx);
 void cayman_emit_msaa_sample_locs(struct radeon_winsys_cs *cs, int nr_samples);
 void cayman_emit_msaa_config(struct radeon_winsys_cs *cs, int nr_samples,
                             int ps_iter_samples);
index d021caaa6c424011927d589ce5ebcf125975da20..6818106ece7b6463f1fabe0ad543627c9d467a82 100644 (file)
@@ -557,6 +557,8 @@ static void declare_system_value(
 {
        struct si_shader_context *si_shader_ctx =
                si_shader_context(&radeon_bld->soa.bld_base);
+       struct lp_build_context *uint_bld = &radeon_bld->soa.bld_base.uint_bld;
+       struct gallivm_state *gallivm = &radeon_bld->gallivm;
        LLVMValueRef value = 0;
 
        switch (decl->Semantic.Name) {
@@ -574,6 +576,27 @@ static void declare_system_value(
                value = get_sample_id(radeon_bld);
                break;
 
+       case TGSI_SEMANTIC_SAMPLEPOS:
+       {
+               LLVMBuilderRef builder = gallivm->builder;
+               LLVMValueRef desc = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_CONST);
+               LLVMValueRef buf_index = lp_build_const_int32(gallivm, NUM_PIPE_CONST_BUFFERS);
+               LLVMValueRef resource = build_indexed_load(si_shader_ctx, desc, buf_index);
+
+               /* offset = sample_id * 8  (8 = 2 floats containing samplepos.xy) */
+               LLVMValueRef offset0 = lp_build_mul_imm(uint_bld, get_sample_id(radeon_bld), 8);
+               LLVMValueRef offset1 = LLVMBuildAdd(builder, offset0, lp_build_const_int32(gallivm, 4), "");
+
+               LLVMValueRef pos[4] = {
+                       load_const(builder, resource, offset0, radeon_bld->soa.bld_base.base.elem_type),
+                       load_const(builder, resource, offset1, radeon_bld->soa.bld_base.base.elem_type),
+                       lp_build_const_float(gallivm, 0),
+                       lp_build_const_float(gallivm, 0)
+               };
+               value = lp_build_gather_values(gallivm, pos, 4);
+               break;
+       }
+
        default:
                assert(!"unknown system value");
                return;
index c08d7034c5570b8993a1adf0d06d890b18e0e2ba..b85a4594156992d552eeb18fa063f396415198ba 100644 (file)
@@ -1859,6 +1859,7 @@ static void si_set_framebuffer_state(struct pipe_context *ctx,
                                     const struct pipe_framebuffer_state *state)
 {
        struct si_context *sctx = (struct si_context *)ctx;
+       struct pipe_constant_buffer constbuf = {0};
        struct r600_surface *surf = NULL;
        struct r600_texture *rtex;
        int i;
@@ -1924,6 +1925,30 @@ static void si_set_framebuffer_state(struct pipe_context *ctx,
        sctx->framebuffer.atom.num_dw += 18; /* MSAA sample locations */
        sctx->framebuffer.atom.dirty = true;
        sctx->msaa_config.dirty = true;
+
+       /* Set sample locations as fragment shader constants. */
+       switch (sctx->framebuffer.nr_samples) {
+       case 1:
+               constbuf.user_buffer = sctx->b.sample_locations_1x;
+               break;
+       case 2:
+               constbuf.user_buffer = sctx->b.sample_locations_2x;
+               break;
+       case 4:
+               constbuf.user_buffer = sctx->b.sample_locations_4x;
+               break;
+       case 8:
+               constbuf.user_buffer = sctx->b.sample_locations_8x;
+               break;
+       case 16:
+               constbuf.user_buffer = sctx->b.sample_locations_16x;
+               break;
+       default:
+               assert(0);
+       }
+       constbuf.buffer_size = sctx->framebuffer.nr_samples * 2 * 4;
+       ctx->set_constant_buffer(ctx, PIPE_SHADER_FRAGMENT,
+                                NUM_PIPE_CONST_BUFFERS, &constbuf);
 }
 
 static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom *atom)