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

Roland Scheidegger sroland at vmware.com
Wed May 7 10:34:50 PDT 2014


Am 07.05.2014 17:56, schrieb Marek Olšák:
> I could enable interpolation of gl_FragCoord at the sample instead of
> centroid and do:
> 
> gl_SamplePos = fract(gl_FragCoord.xy);
> 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.
Intuitively I would have said it should return the per-sample position.
But on second though this isn't all that obvious I guess indeed (in
newer glsl versions is it even valid to use the "normal" interpolation
qualifiers for this like centroid, flat(???), sample)?

btw I guess I'm responsible for the "claims" there might be hw which
could do this directly. This was simply based on d3d11 having an
instruction to query this, and hw usually follows d3d11 pretty closely.
But well maybe not in this case (d3d11 also allows you to query sample
positions not just for the rasterizer but also for the textures).

Roland


> 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
>>> https://urldefense.proofpoint.com/v1/url?u=http://lists.freedesktop.org/mailman/listinfo/mesa-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=F4msKE2WxRzA%2BwN%2B25muztFm5TSPwE8HKJfWfR2NgfY%3D%0A&m=pPcdmCh3O%2BmOAlNWWcq1VayOo4Ja5FsJuuuIky4AIaE%3D%0A&s=f57c7c6e1e0635dfbed3cbde632ebc546300174a33a046ac6dda733290458db5
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://urldefense.proofpoint.com/v1/url?u=http://lists.freedesktop.org/mailman/listinfo/mesa-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=F4msKE2WxRzA%2BwN%2B25muztFm5TSPwE8HKJfWfR2NgfY%3D%0A&m=pPcdmCh3O%2BmOAlNWWcq1VayOo4Ja5FsJuuuIky4AIaE%3D%0A&s=f57c7c6e1e0635dfbed3cbde632ebc546300174a33a046ac6dda733290458db5
> 


More information about the mesa-dev mailing list