[Mesa-dev] [PATCH 5/8] radeonsi: implement SAMPLEPOS fragment shader input

Marek Olšák maraeo at gmail.com
Wed May 7 09:45:31 PDT 2014


It's a pseudo-code that would be inserted at the beginning of the
shader by the shader compiler. gl_SamplePos is always read-only from a
user's point of view.

Marek

On Wed, May 7, 2014 at 6:02 PM, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
> On Wed, May 7, 2014 at 11:56 AM, Marek Olšák <maraeo at gmail.com> wrote:
>> I could enable interpolation of gl_FragCoord at the sample instead of
>> centroid and do:
>>
>> gl_SamplePos = fract(gl_FragCoord.xy);
>
> Is that legal? I didn't think that sample position could be an output,
> at least not with ARB_sample_shading (and not even with
> ARB_gpu_shader5). Perhaps some other extension adds it.
>
>> gl_FragCoord.xy = floor(gl_FragCoord.xy) + vec2(0.5); // center
>>
>> However, I wouldn't be able to get gl_FragCoord at the centroid.
>>
>> I'm also not sure how gl_FragCoord should be interpolated if sample
>> shading is enabled.
>>
>> Marek
>>
>> On Wed, May 7, 2014 at 5:00 PM, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
>>> On Wed, May 7, 2014 at 10:00 AM, Marek Olšák <maraeo at gmail.com> wrote:
>>>> From: Marek Olšák <marek.olsak at amd.com>
>>>>
>>>> The sample positions are read from a constant buffer.
>>>
>>> FWIW I had to do the same thing in both nv50 and nvc0. I had proposed
>>> that this should actually be done directly by the state tracker, but I
>>> think claims were made to the effect that there might be hw which can
>>> look up the positions directly. I figured radeon was such hw, but I
>>> guess not.
>>>
>>> Anyways, seems like a nice refactor would be to have mesa/st (or
>>> mesa/main) supply the constbufs and rip out the extra logic from
>>> nv50/nvc0/radeonsi. [Certainly don't have to do it now, esp now that
>>> you've done it this way.] The sample count is already handled this way
>>> by mesa core.
>>>
>>>   -ilia
>>>
>>>> ---
>>>>  src/gallium/drivers/radeon/cayman_msaa.c      | 17 +++++++++++++++++
>>>>  src/gallium/drivers/radeon/r600_pipe_common.c |  1 +
>>>>  src/gallium/drivers/radeon/r600_pipe_common.h | 10 ++++++++++
>>>>  src/gallium/drivers/radeonsi/si_shader.c      | 23 +++++++++++++++++++++++
>>>>  src/gallium/drivers/radeonsi/si_state.c       | 25 +++++++++++++++++++++++++
>>>>  5 files changed, 76 insertions(+)
>>>>
>>>> diff --git a/src/gallium/drivers/radeon/cayman_msaa.c b/src/gallium/drivers/radeon/cayman_msaa.c
>>>> index 8727f3e..47fc5c4 100644
>>>> --- a/src/gallium/drivers/radeon/cayman_msaa.c
>>>> +++ b/src/gallium/drivers/radeon/cayman_msaa.c
>>>> @@ -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) {
>>>> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
>>>> index 70c4d1a..4c6cf0e 100644
>>>> --- a/src/gallium/drivers/radeon/r600_pipe_common.c
>>>> +++ b/src/gallium/drivers/radeon/r600_pipe_common.c
>>>> @@ -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);
>>>> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
>>>> index 4c3e9ce..8862d31 100644
>>>> --- a/src/gallium/drivers/radeon/r600_pipe_common.h
>>>> +++ b/src/gallium/drivers/radeon/r600_pipe_common.h
>>>> @@ -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);
>>>> diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
>>>> index 0195e54..d8b7b9c 100644
>>>> --- a/src/gallium/drivers/radeonsi/si_shader.c
>>>> +++ b/src/gallium/drivers/radeonsi/si_shader.c
>>>> @@ -559,6 +559,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) {
>>>> @@ -576,6 +578,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;
>>>> diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
>>>> index fd9de05..3c1af06 100644
>>>> --- a/src/gallium/drivers/radeonsi/si_state.c
>>>> +++ b/src/gallium/drivers/radeonsi/si_state.c
>>>> @@ -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)
>>>> --
>>>> 1.9.1
>>>>
>>>> _______________________________________________
>>>> mesa-dev mailing list
>>>> mesa-dev at lists.freedesktop.org
>>>> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list