[Mesa-dev] [RFC PATCH] radeonsi: set a per-buffer flag that disables inter-process sharing (v2)
Samuel Pitoiset
samuel.pitoiset at gmail.com
Thu Jul 20 11:06:11 UTC 2017
On 07/20/2017 04:20 AM, zhoucm1 wrote:
>
>
> On 2017年07月19日 23:34, Marek Olšák wrote:
>>
>>
>> On Jul 19, 2017 3:36 AM, "zhoucm1" <david1.zhou at amd.com
>> <mailto:david1.zhou at amd.com>> wrote:
>>
>>
>>
>> On 2017年07月19日 04:08, Marek Olšák wrote:
>>
>> From: Marek Olšák <marek.olsak at amd.com
>> <mailto:marek.olsak at amd.com>>
>>
>> For lower overhead in the CS ioctl.
>> Winsys allocators are not used with interprocess-sharable
>> resources.
>>
>> Hi Marek,
>>
>> Could I know from how your this way reduces overhead in CS ioctl?
>> reusing BO to short bo list?
>>
>>
>> The kernel part of the work hasn't been done yet. The idea is that
>> nonsharable buffers don't have to be revalidated by TTM,
> OK, Maybe I only can see the whole picture of this idea when you
> complete kernel part.
> Out of curious, why/how can nonsharable buffers be revalidated by TTM
> without exposing like amdgpu_bo_make_resident api?
>
> With mentioned in another thread, if we can expose make_resident api, we
> can remove bo_list, even we can remove reservation operation in CS ioctl.
> And now, I think our bo list is a very bad design,
> first, umd must create bo list for every command submission, this is a
> extra cpu overhead compared with traditional way.
> second, kernel also have to iterate the list, when bo list is too long,
> like OpenCL program, they always throw several thousands BOs to bo list,
> reservation must keep these thousands ww_mutex safe, CPU overhead is too
> big.
>
> So I strongly suggest we should expose make_resident api to user space.
> if cannot, I want to know any specific reason to see if we can solve it.
Introducing a make_resident API will also help ARB_bindless_texture a
lot, because currently when a texture is marked as resident, we have to
re-validate the related buffers for every new CS, like traditional
buffers. With a resident BO list the whole mechanism could be skipped.
>
>
> Regards,
> David Zhou
>> so it should remove a lot of kernel overhead and the BO list remains
>> the same.
>>
>> Marek
>>
>>
>>
>> Thanks,
>> David Zhou
>>
>>
>> v2: It shouldn't crash anymore, but the kernel will reject the
>> new flag.
>> ---
>> src/gallium/drivers/radeon/r600_buffer_common.c | 7 +++++
>> src/gallium/drivers/radeon/radeon_winsys.h | 20 +++++++++++---
>> src/gallium/winsys/amdgpu/drm/amdgpu_bo.c | 36
>> ++++++++++++++++---------
>> src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 27
>> +++++++++++--------
>> 4 files changed, 62 insertions(+), 28 deletions(-)
>>
>> diff --git a/src/gallium/drivers/radeon/r600_buffer_common.c
>> b/src/gallium/drivers/radeon/r600_buffer_common.c
>> index dd1c209..2747ac4 100644
>> --- a/src/gallium/drivers/radeon/r600_buffer_common.c
>> +++ b/src/gallium/drivers/radeon/r600_buffer_common.c
>> @@ -160,20 +160,27 @@ void r600_init_resource_fields(struct
>> r600_common_screen *rscreen,
>> }
>> /* Tiled textures are unmappable. Always put them in
>> VRAM. */
>> if ((res->b.b.target != PIPE_BUFFER &&
>> !rtex->surface.is_linear) ||
>> res->flags & R600_RESOURCE_FLAG_UNMAPPABLE) {
>> res->domains = RADEON_DOMAIN_VRAM;
>> res->flags |= RADEON_FLAG_NO_CPU_ACCESS |
>> RADEON_FLAG_GTT_WC;
>> }
>> + /* Only displayable single-sample textures can be
>> shared between
>> + * processes. */
>> + if (res->b.b.target == PIPE_BUFFER ||
>> + res->b.b.nr_samples >= 2 ||
>> + rtex->surface.micro_tile_mode !=
>> RADEON_MICRO_MODE_DISPLAY)
>> + res->flags |= RADEON_FLAG_NO_INTERPROCESS_SHARING;
>> +
>> /* If VRAM is just stolen system memory, allow both
>> VRAM and
>> * GTT, whichever has free space. If a buffer is
>> evicted from
>> * VRAM to GTT, it will stay there.
>> *
>> * DRM 3.6.0 has good BO move throttling, so we can
>> allow VRAM-only
>> * placements even with a low amount of stolen VRAM.
>> */
>> if (!rscreen->info.has_dedicated_vram &&
>> (rscreen->info.drm_major < 3 ||
>> rscreen->info.drm_minor < 6) &&
>> res->domains == RADEON_DOMAIN_VRAM) {
>> diff --git a/src/gallium/drivers/radeon/radeon_winsys.h
>> b/src/gallium/drivers/radeon/radeon_winsys.h
>> index 351edcd..0abcb56 100644
>> --- a/src/gallium/drivers/radeon/radeon_winsys.h
>> +++ b/src/gallium/drivers/radeon/radeon_winsys.h
>> @@ -47,20 +47,21 @@ enum radeon_bo_domain { /* bitfield */
>> RADEON_DOMAIN_GTT = 2,
>> RADEON_DOMAIN_VRAM = 4,
>> RADEON_DOMAIN_VRAM_GTT = RADEON_DOMAIN_VRAM |
>> RADEON_DOMAIN_GTT
>> };
>> enum radeon_bo_flag { /* bitfield */
>> RADEON_FLAG_GTT_WC = (1 << 0),
>> RADEON_FLAG_NO_CPU_ACCESS = (1 << 1),
>> RADEON_FLAG_NO_SUBALLOC = (1 << 2),
>> RADEON_FLAG_SPARSE = (1 << 3),
>> + RADEON_FLAG_NO_INTERPROCESS_SHARING = (1 << 4),
>> };
>> enum radeon_bo_usage { /* bitfield */
>> RADEON_USAGE_READ = 2,
>> RADEON_USAGE_WRITE = 4,
>> RADEON_USAGE_READWRITE = RADEON_USAGE_READ |
>> RADEON_USAGE_WRITE,
>> /* The winsys ensures that the CS submission will be
>> scheduled after
>> * previously flushed CSs referencing this BO in a
>> conflicting way.
>> */
>> @@ -685,28 +686,33 @@ static inline enum radeon_bo_domain
>> radeon_domain_from_heap(enum radeon_heap hea
>> default:
>> assert(0);
>> return (enum radeon_bo_domain)0;
>> }
>> }
>> static inline unsigned radeon_flags_from_heap(enum
>> radeon_heap heap)
>> {
>> switch (heap) {
>> case RADEON_HEAP_VRAM_NO_CPU_ACCESS:
>> - return RADEON_FLAG_GTT_WC | RADEON_FLAG_NO_CPU_ACCESS;
>> + return RADEON_FLAG_GTT_WC |
>> + RADEON_FLAG_NO_CPU_ACCESS |
>> + RADEON_FLAG_NO_INTERPROCESS_SHARING;
>> +
>> case RADEON_HEAP_VRAM:
>> case RADEON_HEAP_VRAM_GTT:
>> case RADEON_HEAP_GTT_WC:
>> - return RADEON_FLAG_GTT_WC;
>> + return RADEON_FLAG_GTT_WC |
>> + RADEON_FLAG_NO_INTERPROCESS_SHARING;
>> +
>> case RADEON_HEAP_GTT:
>> default:
>> - return 0;
>> + return RADEON_FLAG_NO_INTERPROCESS_SHARING;
>> }
>> }
>> /* The pb cache bucket is chosen to minimize pb_cache misses.
>> * It must be between 0 and 3 inclusive.
>> */
>> static inline unsigned radeon_get_pb_cache_bucket_index(enum
>> radeon_heap heap)
>> {
>> switch (heap) {
>> case RADEON_HEAP_VRAM_NO_CPU_ACCESS:
>> @@ -724,22 +730,28 @@ static inline unsigned
>> radeon_get_pb_cache_bucket_index(enum radeon_heap heap)
>> /* Return the heap index for winsys allocators, or -1 on
>> failure. */
>> static inline int radeon_get_heap_index(enum
>> radeon_bo_domain domain,
>> enum radeon_bo_flag
>> flags)
>> {
>> /* VRAM implies WC (write combining) */
>> assert(!(domain & RADEON_DOMAIN_VRAM) || flags &
>> RADEON_FLAG_GTT_WC);
>> /* NO_CPU_ACCESS implies VRAM only. */
>> assert(!(flags & RADEON_FLAG_NO_CPU_ACCESS) || domain ==
>> RADEON_DOMAIN_VRAM);
>> + /* Resources with interprocess sharing don't use any
>> winsys allocators. */
>> + if (!(flags & RADEON_FLAG_NO_INTERPROCESS_SHARING))
>> + return -1;
>> +
>> /* Unsupported flags: NO_SUBALLOC, SPARSE. */
>> - if (flags & ~(RADEON_FLAG_GTT_WC |
>> RADEON_FLAG_NO_CPU_ACCESS))
>> + if (flags & ~(RADEON_FLAG_GTT_WC |
>> + RADEON_FLAG_NO_CPU_ACCESS |
>> + RADEON_FLAG_NO_INTERPROCESS_SHARING))
>> return -1;
>> switch (domain) {
>> case RADEON_DOMAIN_VRAM:
>> if (flags & RADEON_FLAG_NO_CPU_ACCESS)
>> return RADEON_HEAP_VRAM_NO_CPU_ACCESS;
>> else
>> return RADEON_HEAP_VRAM;
>> case RADEON_DOMAIN_VRAM_GTT:
>> return RADEON_HEAP_VRAM_GTT;
>> diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c
>> b/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c
>> index 97bbe23..06b8198 100644
>> --- a/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c
>> +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c
>> @@ -31,20 +31,24 @@
>> #include "amdgpu_cs.h"
>> #include "os/os_time.h"
>> #include "state_tracker/drm_driver.h"
>> #include <amdgpu_drm.h>
>> #include <xf86drm.h>
>> #include <stdio.h>
>> #include <inttypes.h>
>> +#ifndef AMDGPU_GEM_CREATE_NO_INTERPROCESS_SHARING
>> +#define AMDGPU_GEM_CREATE_NO_INTERPROCESS_SHARING (1 << 6)
>> +#endif
>> +
>> /* Set to 1 for verbose output showing committed sparse
>> buffer ranges. */
>> #define DEBUG_SPARSE_COMMITS 0
>> struct amdgpu_sparse_backing_chunk {
>> uint32_t begin, end;
>> };
>> static struct pb_buffer *
>> amdgpu_bo_create(struct radeon_winsys *rws,
>> uint64_t size,
>> @@ -395,20 +399,22 @@ static struct amdgpu_winsys_bo
>> *amdgpu_create_bo(struct amdgpu_winsys *ws,
>> if (initial_domain & RADEON_DOMAIN_VRAM)
>> request.preferred_heap |= AMDGPU_GEM_DOMAIN_VRAM;
>> if (initial_domain & RADEON_DOMAIN_GTT)
>> request.preferred_heap |= AMDGPU_GEM_DOMAIN_GTT;
>> if (flags & RADEON_FLAG_NO_CPU_ACCESS)
>> request.flags |= AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
>> if (flags & RADEON_FLAG_GTT_WC)
>> request.flags |= AMDGPU_GEM_CREATE_CPU_GTT_USWC;
>> + if (flags & RADEON_FLAG_NO_INTERPROCESS_SHARING)
>> + request.flags |= AMDGPU_GEM_CREATE_NO_INTERPROCESS_SHARING;
>> r = amdgpu_bo_alloc(ws->dev, &request, &buf_handle);
>> if (r) {
>> fprintf(stderr, "amdgpu: Failed to allocate a buffer:\n");
>> fprintf(stderr, "amdgpu: size : %"PRIu64"
>> bytes\n", size);
>> fprintf(stderr, "amdgpu: alignment : %u bytes\n",
>> alignment);
>> fprintf(stderr, "amdgpu: domains : %u\n",
>> initial_domain);
>> goto error_bo_alloc;
>> }
>> @@ -1127,21 +1133,21 @@ static void
>> amdgpu_buffer_set_metadata(struct pb_buffer *_buf,
>> static struct pb_buffer *
>> amdgpu_bo_create(struct radeon_winsys *rws,
>> uint64_t size,
>> unsigned alignment,
>> enum radeon_bo_domain domain,
>> enum radeon_bo_flag flags)
>> {
>> struct amdgpu_winsys *ws = amdgpu_winsys(rws);
>> struct amdgpu_winsys_bo *bo;
>> - unsigned usage = 0, pb_cache_bucket;
>> + unsigned usage = 0, pb_cache_bucket = 0;
>> /* VRAM implies WC. This is not optional. */
>> assert(!(domain & RADEON_DOMAIN_VRAM) || flags &
>> RADEON_FLAG_GTT_WC);
>> /* NO_CPU_ACCESS is valid with VRAM only. */
>> assert(domain == RADEON_DOMAIN_VRAM || !(flags &
>> RADEON_FLAG_NO_CPU_ACCESS));
>> /* Sub-allocate small buffers from slabs. */
>> if (!(flags & (RADEON_FLAG_NO_SUBALLOC |
>> RADEON_FLAG_SPARSE)) &&
>> size <= (1 << AMDGPU_SLAB_MAX_SIZE_LOG2) &&
>> @@ -1182,48 +1188,52 @@ no_slab:
>> /* This flag is irrelevant for the cache. */
>> flags &= ~RADEON_FLAG_NO_SUBALLOC;
>> /* Align size to page size. This is the minimum
>> alignment for normal
>> * BOs. Aligning this here helps the cached bufmgr.
>> Especially small BOs,
>> * like constant/uniform buffers, can benefit from better
>> and more reuse.
>> */
>> size = align64(size, ws->info.gart_page_size);
>> alignment = align(alignment, ws->info.gart_page_size);
>> - int heap = radeon_get_heap_index(domain, flags);
>> - assert(heap >= 0 && heap < RADEON_MAX_CACHED_HEAPS);
>> - usage = 1 << heap; /* Only set one usage bit for each heap. */
>> + bool use_reusable_pool = flags &
>> RADEON_FLAG_NO_INTERPROCESS_SHARING;
>> - pb_cache_bucket = radeon_get_pb_cache_bucket_index(heap);
>> - assert(pb_cache_bucket < ARRAY_SIZE(ws->bo_cache.buckets));
>> + if (use_reusable_pool) {
>> + int heap = radeon_get_heap_index(domain, flags);
>> + assert(heap >= 0 && heap < RADEON_MAX_CACHED_HEAPS);
>> + usage = 1 << heap; /* Only set one usage bit for each
>> heap. */
>> - /* Get a buffer from the cache. */
>> - bo = (struct amdgpu_winsys_bo*)
>> - pb_cache_reclaim_buffer(&ws->bo_cache, size,
>> alignment, usage,
>> - pb_cache_bucket);
>> - if (bo)
>> - return &bo->base;
>> + pb_cache_bucket = radeon_get_pb_cache_bucket_index(heap);
>> + assert(pb_cache_bucket <
>> ARRAY_SIZE(ws->bo_cache.buckets));
>> +
>> + /* Get a buffer from the cache. */
>> + bo = (struct amdgpu_winsys_bo*)
>> + pb_cache_reclaim_buffer(&ws->bo_cache, size,
>> alignment, usage,
>> + pb_cache_bucket);
>> + if (bo)
>> + return &bo->base;
>> + }
>> /* Create a new one. */
>> bo = amdgpu_create_bo(ws, size, alignment, usage, domain,
>> flags,
>> pb_cache_bucket);
>> if (!bo) {
>> /* Clear the cache and try again. */
>> pb_slabs_reclaim(&ws->bo_slabs);
>> pb_cache_release_all_buffers(&ws->bo_cache);
>> bo = amdgpu_create_bo(ws, size, alignment, usage,
>> domain, flags,
>> pb_cache_bucket);
>> if (!bo)
>> return NULL;
>> }
>> - bo->u.real.use_reusable_pool = true;
>> + bo->u.real.use_reusable_pool = use_reusable_pool;
>> return &bo->base;
>> }
>> static struct pb_buffer *amdgpu_bo_from_handle(struct
>> radeon_winsys *rws,
>> struct winsys_handle *whandle,
>> unsigned *stride,
>> unsigned *offset)
>> {
>> struct amdgpu_winsys *ws = amdgpu_winsys(rws);
>> struct amdgpu_winsys_bo *bo;
>> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>> b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>> index 8027a5f..15e9d38 100644
>> --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>> @@ -907,21 +907,21 @@ static void
>> radeon_bo_set_metadata(struct pb_buffer *_buf,
>> static struct pb_buffer *
>> radeon_winsys_bo_create(struct radeon_winsys *rws,
>> uint64_t size,
>> unsigned alignment,
>> enum radeon_bo_domain domain,
>> enum radeon_bo_flag flags)
>> {
>> struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
>> struct radeon_bo *bo;
>> - unsigned usage = 0, pb_cache_bucket;
>> + unsigned usage = 0, pb_cache_bucket = 0;
>> assert(!(flags & RADEON_FLAG_SPARSE)); /* not supported */
>> /* Only 32-bit sizes are supported. */
>> if (size > UINT_MAX)
>> return NULL;
>> /* VRAM implies WC. This is not optional. */
>> if (domain & RADEON_DOMAIN_VRAM)
>> flags |= RADEON_FLAG_GTT_WC;
>> @@ -962,46 +962,51 @@ no_slab:
>> /* This flag is irrelevant for the cache. */
>> flags &= ~RADEON_FLAG_NO_SUBALLOC;
>> /* Align size to page size. This is the minimum
>> alignment for normal
>> * BOs. Aligning this here helps the cached bufmgr.
>> Especially small BOs,
>> * like constant/uniform buffers, can benefit from
>> better and more reuse.
>> */
>> size = align(size, ws->info.gart_page_size);
>> alignment = align(alignment, ws->info.gart_page_size);
>> - int heap = radeon_get_heap_index(domain, flags);
>> - assert(heap >= 0 && heap < RADEON_MAX_CACHED_HEAPS);
>> - usage = 1 << heap; /* Only set one usage bit for each
>> heap. */
>> + bool use_reusable_pool = flags &
>> RADEON_FLAG_NO_INTERPROCESS_SHARING;
>> - pb_cache_bucket = radeon_get_pb_cache_bucket_index(heap);
>> - assert(pb_cache_bucket < ARRAY_SIZE(ws->bo_cache.buckets));
>> + /* Shared resources don't use cached heaps. */
>> + if (use_reusable_pool) {
>> + int heap = radeon_get_heap_index(domain, flags);
>> + assert(heap >= 0 && heap < RADEON_MAX_CACHED_HEAPS);
>> + usage = 1 << heap; /* Only set one usage bit for each
>> heap. */
>> - bo = radeon_bo(pb_cache_reclaim_buffer(&ws->bo_cache,
>> size, alignment,
>> - usage,
>> pb_cache_bucket));
>> - if (bo)
>> - return &bo->base;
>> + pb_cache_bucket = radeon_get_pb_cache_bucket_index(heap);
>> + assert(pb_cache_bucket <
>> ARRAY_SIZE(ws->bo_cache.buckets));
>> +
>> + bo = radeon_bo(pb_cache_reclaim_buffer(&ws->bo_cache,
>> size, alignment,
>> + usage, pb_cache_bucket));
>> + if (bo)
>> + return &bo->base;
>> + }
>> bo = radeon_create_bo(ws, size, alignment, usage,
>> domain, flags,
>> pb_cache_bucket);
>> if (!bo) {
>> /* Clear the cache and try again. */
>> if (ws->info.has_virtual_memory)
>> pb_slabs_reclaim(&ws->bo_slabs);
>> pb_cache_release_all_buffers(&ws->bo_cache);
>> bo = radeon_create_bo(ws, size, alignment, usage,
>> domain, flags,
>> pb_cache_bucket);
>> if (!bo)
>> return NULL;
>> }
>> - bo->u.real.use_reusable_pool = true;
>> + bo->u.real.use_reusable_pool = use_reusable_pool;
>> mtx_lock(&ws->bo_handles_mutex);
>> util_hash_table_set(ws->bo_handles,
>> (void*)(uintptr_t)bo->handle, bo);
>> mtx_unlock(&ws->bo_handles_mutex);
>> return &bo->base;
>> }
>> static struct pb_buffer *radeon_winsys_bo_from_ptr(struct
>> radeon_winsys *rws,
>> void *pointer, uint64_t size)
>>
>>
>>
>
>
>
> N�n�r����)em�h�yhiם�w^��
>
More information about the mesa-dev
mailing list