[Mesa-dev] [PATCH 4/4] winsys/amdgpu: fix VDPAU interop by having one amdgpu_winsys_bo per BO
Marek Olšák
maraeo at gmail.com
Mon Jul 16 17:24:16 UTC 2018
From: Marek Olšák <marek.olsak at amd.com>
Dependencies between rings are inserted correctly if a buffer is
represented by only one unique amdgpu_winsys_bo instance.
Use a hash table keyed by amdgpu_bo_handle to have exactly one
amdgpu_winsys_bo per amdgpu_bo_handle.
---
src/gallium/winsys/amdgpu/drm/amdgpu_bo.c | 26 +++++++++++++++++++
src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c | 5 ++++
src/gallium/winsys/amdgpu/drm/amdgpu_winsys.h | 5 ++++
3 files changed, 36 insertions(+)
diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c b/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c
index b7f49a1159f..3172e9bdde3 100644
--- a/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c
+++ b/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c
@@ -21,20 +21,21 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*/
#include "amdgpu_cs.h"
#include "util/os_time.h"
+#include "util/u_hash_table.h"
#include "state_tracker/drm_driver.h"
#include <amdgpu_drm.h>
#include <xf86drm.h>
#include <stdio.h>
#include <inttypes.h>
#ifndef AMDGPU_GEM_CREATE_VM_ALWAYS_VALID
#define AMDGPU_GEM_CREATE_VM_ALWAYS_VALID (1 << 6)
#endif
@@ -172,20 +173,24 @@ void amdgpu_bo_destroy(struct pb_buffer *_buf)
assert(bo->bo && "must not be called for slab entries");
if (ws->debug_all_bos) {
simple_mtx_lock(&ws->global_bo_list_lock);
LIST_DEL(&bo->u.real.global_list_item);
ws->num_buffers--;
simple_mtx_unlock(&ws->global_bo_list_lock);
}
+ simple_mtx_lock(&ws->bo_export_table_lock);
+ util_hash_table_remove(ws->bo_export_table, bo->bo);
+ simple_mtx_unlock(&ws->bo_export_table_lock);
+
amdgpu_bo_va_op(bo->bo, 0, bo->base.size, bo->va, 0, AMDGPU_VA_OP_UNMAP);
amdgpu_va_range_free(bo->u.real.va_handle);
amdgpu_bo_free(bo->bo);
amdgpu_bo_remove_fences(bo);
if (bo->initial_domain & RADEON_DOMAIN_VRAM)
ws->allocated_vram -= align64(bo->base.size, ws->info.gart_page_size);
else if (bo->initial_domain & RADEON_DOMAIN_GTT)
ws->allocated_gtt -= align64(bo->base.size, ws->info.gart_page_size);
@@ -1284,20 +1289,32 @@ static struct pb_buffer *amdgpu_bo_from_handle(struct radeon_winsys *rws,
type = amdgpu_bo_handle_type_dma_buf_fd;
break;
default:
return NULL;
}
r = amdgpu_bo_import(ws->dev, type, whandle->handle, &result);
if (r)
return NULL;
+ simple_mtx_lock(&ws->bo_export_table_lock);
+ bo = util_hash_table_get(ws->bo_export_table, result.buf_handle);
+
+ /* If the amdgpu_winsys_bo instance already exists, bump the reference
+ * counter and return it.
+ */
+ if (bo) {
+ p_atomic_inc(&bo->base.reference.count);
+ simple_mtx_unlock(&ws->bo_export_table_lock);
+ return &bo->base;
+ }
+
/* Get initial domains. */
r = amdgpu_bo_query_info(result.buf_handle, &info);
if (r)
goto error;
r = amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general,
result.alloc_size, 1 << 20, 0, &va, &va_handle,
AMDGPU_VA_RANGE_HIGH);
if (r)
goto error;
@@ -1335,37 +1352,42 @@ static struct pb_buffer *amdgpu_bo_from_handle(struct radeon_winsys *rws,
if (bo->initial_domain & RADEON_DOMAIN_VRAM)
ws->allocated_vram += align64(bo->base.size, ws->info.gart_page_size);
else if (bo->initial_domain & RADEON_DOMAIN_GTT)
ws->allocated_gtt += align64(bo->base.size, ws->info.gart_page_size);
amdgpu_bo_export(bo->bo, amdgpu_bo_handle_type_kms_noimport, &bo->u.real.kms_handle);
amdgpu_add_buffer_to_global_list(bo);
+ util_hash_table_set(ws->bo_export_table, bo->bo, bo);
+ simple_mtx_unlock(&ws->bo_export_table_lock);
+
return &bo->base;
error:
+ simple_mtx_unlock(&ws->bo_export_table_lock);
if (bo)
FREE(bo);
if (va_handle)
amdgpu_va_range_free(va_handle);
amdgpu_bo_free(result.buf_handle);
return NULL;
}
static bool amdgpu_bo_get_handle(struct pb_buffer *buffer,
unsigned stride, unsigned offset,
unsigned slice_size,
struct winsys_handle *whandle)
{
struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(buffer);
+ struct amdgpu_winsys *ws = bo->ws;
enum amdgpu_bo_handle_type type;
int r;
/* Don't allow exports of slab entries and sparse buffers. */
if (!bo->bo)
return false;
bo->u.real.use_reusable_pool = false;
switch (whandle->type) {
@@ -1379,20 +1401,24 @@ static bool amdgpu_bo_get_handle(struct pb_buffer *buffer,
type = amdgpu_bo_handle_type_kms;
break;
default:
return false;
}
r = amdgpu_bo_export(bo->bo, type, &whandle->handle);
if (r)
return false;
+ simple_mtx_lock(&ws->bo_export_table_lock);
+ util_hash_table_set(ws->bo_export_table, bo->bo, bo);
+ simple_mtx_unlock(&ws->bo_export_table_lock);
+
whandle->stride = stride;
whandle->offset = offset;
whandle->offset += slice_size * whandle->layer;
bo->is_shared = true;
return true;
}
static struct pb_buffer *amdgpu_bo_from_ptr(struct radeon_winsys *rws,
void *pointer, uint64_t size)
{
diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c b/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c
index db7a4d7033c..882f500bc69 100644
--- a/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c
+++ b/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c
@@ -85,21 +85,23 @@ static void amdgpu_winsys_destroy(struct radeon_winsys *rws)
if (ws->reserve_vmid)
amdgpu_vm_unreserve_vmid(ws->dev, 0);
if (util_queue_is_initialized(&ws->cs_queue))
util_queue_destroy(&ws->cs_queue);
simple_mtx_destroy(&ws->bo_fence_lock);
pb_slabs_deinit(&ws->bo_slabs);
pb_cache_deinit(&ws->bo_cache);
+ util_hash_table_destroy(ws->bo_export_table);
simple_mtx_destroy(&ws->global_bo_list_lock);
+ simple_mtx_destroy(&ws->bo_export_table_lock);
do_winsys_deinit(ws);
FREE(rws);
}
static void amdgpu_winsys_query_info(struct radeon_winsys *rws,
struct radeon_info *info)
{
*info = ((struct amdgpu_winsys *)rws)->info;
}
@@ -307,22 +309,25 @@ amdgpu_winsys_create(int fd, const struct pipe_screen_config *config,
ws->base.cs_request_feature = amdgpu_cs_request_feature;
ws->base.query_value = amdgpu_query_value;
ws->base.read_registers = amdgpu_read_registers;
ws->base.get_chip_name = amdgpu_get_chip_name;
amdgpu_bo_init_functions(ws);
amdgpu_cs_init_functions(ws);
amdgpu_surface_init_functions(ws);
LIST_INITHEAD(&ws->global_bo_list);
+ ws->bo_export_table = util_hash_table_create(hash_pointer, compare_pointers);
+
(void) simple_mtx_init(&ws->global_bo_list_lock, mtx_plain);
(void) simple_mtx_init(&ws->bo_fence_lock, mtx_plain);
+ (void) simple_mtx_init(&ws->bo_export_table_lock, mtx_plain);
if (!util_queue_init(&ws->cs_queue, "cs", 8, 1,
UTIL_QUEUE_INIT_RESIZE_IF_FULL)) {
amdgpu_winsys_destroy(&ws->base);
simple_mtx_unlock(&dev_tab_mutex);
return NULL;
}
/* Create the screen at the end. The winsys must be initialized
* completely.
diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.h b/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.h
index 8079255e4cf..c355eff5262 100644
--- a/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.h
+++ b/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.h
@@ -78,20 +78,25 @@ struct amdgpu_winsys {
bool check_vm;
bool debug_all_bos;
bool reserve_vmid;
bool zero_all_vram_allocs;
/* List of all allocated buffers */
simple_mtx_t global_bo_list_lock;
struct list_head global_bo_list;
unsigned num_buffers;
+
+ /* For returning the same amdgpu_winsys_bo instance for exported
+ * and re-imported buffers. */
+ struct util_hash_table *bo_export_table;
+ simple_mtx_t bo_export_table_lock;
};
static inline struct amdgpu_winsys *
amdgpu_winsys(struct radeon_winsys *base)
{
return (struct amdgpu_winsys*)base;
}
void amdgpu_surface_init_functions(struct amdgpu_winsys *ws);
--
2.17.1
More information about the mesa-dev
mailing list