[Mesa-dev] [PATCH 03/13] gallium/util: add threaded_context as a pipe_context wrapper

Marek Olšák maraeo at gmail.com
Fri May 12 18:46:23 UTC 2017


[snip]
>> +static unsigned
>> +tc_improve_map_buffer_flags(struct threaded_context *tc,
>> +                            struct threaded_resource *tres, unsigned
>> usage,
>> +                            unsigned offset, unsigned size)
>> +{
>> +   /* Handle CPU reads trivially. */
>> +   if (usage & PIPE_TRANSFER_READ) {
>> +      /* Driver aren't allowed to do buffer invalidations. */
>> +      return (usage & ~PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) |
>> +             TC_TRANSFER_MAP_NO_INVALIDATE |
>> +             TC_TRANSFER_MAP_IGNORE_VALID_RANGE;
>> +   }
>> +
>> +   /* Sparse buffers can't be mapped directly. Use a staging buffer. */
>> +   if (tres->b.flags & PIPE_RESOURCE_FLAG_SPARSE) {
>> +      return (usage & ~(PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE |
>> +                        PIPE_TRANSFER_UNSYNCHRONIZED)) |
>> +             PIPE_TRANSFER_DISCARD_RANGE |
>
>
> Why are we allowed to discard here? Even when a range is mapped only for
> writing, we can't just assume that the whole range will be written by the
> application.
>
> Also, why do we clear the unsynchronized flag? As I understand the code,
we
> do need to synchronize the threads because we're going to use a staging
> buffer. But theoretically, if the driver had a way to do the staging copy
> without waiting for previously submitted draws, it could do so. So... I
> don't think it has a visible effect right now, but I'd rather not remove
the
> unsynchronized flag here.
>
> This may need a bit of clarification in the big comment in the header
file.

That code was indeed completely wrong. I've changed it to this and I moved
this block to the beginning of the function (before the READ handling):

   /* Sparse buffers can't be mapped directly and can't be reallocated
    * (fully invalidated). That may just be a radeonsi limitation, but
    * the threaded context must obey it with radeonsi.
    */
   if (tres->b.flags & PIPE_RESOURCE_FLAG_SPARSE) {
      /* We can use DISCARD_RANGE instead of full discard. This is the only
       * fast path for sparse buffers that doesn't need thread
synchronization.
       */
      if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE)
         usage |= PIPE_TRANSFER_DISCARD_RANGE;

      /* Allow DISCARD_WHOLE_RESOURCE and infering UNSYNCHRONIZED in
drivers.
       * The threaded context doesn't do unsychronized mappings and
invalida-
       * tions of sparse buffers, therefore a correct driver behavior won't
       * result in an incorrect behavior with the threaded context.
       */
      return usage;
   }



>
>
>
>> +             TC_TRANSFER_MAP_NO_INVALIDATE |
>> +             TC_TRANSFER_MAP_IGNORE_VALID_RANGE;
>> +   }

[snip]
>> +         ttrans->b.level = 0;
>> +         ttrans->b.usage = usage;
>> +         ttrans->b.box = *box;
>> +         ttrans->b.stride = 0;
>> +         ttrans->b.layer_stride = 0;
>> +         *transfer = &ttrans->b;
>> +         return map + (box->x % tc->map_buffer_alignment);
>> +      }
>> +   }
>> +
>> +   /* Unsychronized buffer mappings don't have to synchronize the
thread.
>> */
>> +   if (!(usage & TC_TRANSFER_MAP_THREADED_UNSYNC))
>> +      tc_sync_msg(tc, resource->target != PIPE_BUFFER ? "  texture" :
>> +                      usage & PIPE_TRANSFER_DISCARD_RANGE ? "
>> discard_range" :
>> +                      usage & PIPE_TRANSFER_READ ? "  read" : "  ??");
>> +
>> +   return pipe->transfer_map(pipe, tres->latest ? tres->latest :
>> resource,
>> +                             level, usage, box, transfer);
>
>
> The ternary operator here should be unnecessary -- tres->latest should
> always be non-NULL.

It's necessary because this codepath is also used by textures where
tres->latest == NULL because it's not initialized explicitly.

[snip]
>> +
>> +static boolean
>> +tc_generate_mipmap(struct pipe_context *_pipe,
>> +                   struct pipe_resource *res,
>> +                   enum pipe_format format,
>> +                   unsigned base_level,
>> +                   unsigned last_level,
>> +                   unsigned first_layer,
>> +                   unsigned last_layer)
>> +{
>> +   struct threaded_context *tc = threaded_context(_pipe);
>> +   struct pipe_context *pipe = tc->pipe;
>> +   struct pipe_screen *screen = pipe->screen;
>> +   unsigned bind = PIPE_BIND_SAMPLER_VIEW;
>> +
>> +   if (util_format_is_depth_or_stencil(format))
>> +      bind = PIPE_BIND_DEPTH_STENCIL;
>> +   else
>> +      bind = PIPE_BIND_RENDER_TARGET;
>> +
>> +   if (!screen->is_format_supported(screen, format, res->target,
>> +                                    res->nr_samples, bind))
>> +      return false;
>
>
> This feels like the kind of thing the state tracker should be checking
> before it calls this function...

True, but the Gallium interface is currently defined such that drivers do
it.

Marek
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170512/53ffa995/attachment-0001.html>


More information about the mesa-dev mailing list