From 273cc1a69887df2bccfab96120f992c506c9035e Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 6 Nov 2008 00:40:06 +0100 Subject: radeon: lib radeon add bo & cs gem backend --- libdrm/radeon/radeon_cs_gem.c | 266 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 libdrm/radeon/radeon_cs_gem.c (limited to 'libdrm/radeon/radeon_cs_gem.c') diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c new file mode 100644 index 00000000..7ed5780b --- /dev/null +++ b/libdrm/radeon/radeon_cs_gem.c @@ -0,0 +1,266 @@ +/* + * Copyright © 2008 Jérôme Glisse + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * 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. + */ +/* + * Authors: + * Jérôme Glisse + */ +#include +#include +#include "radeon_cs.h" +#include "radeon_cs_gem.h" +#include "radeon_bo_gem.h" +#include "drm.h" +#include "radeon_drm.h" + +#pragma pack(1) +struct cs_reloc_gem { + uint32_t handle; + uint32_t domains; + uint32_t soffset; + uint32_t eoffset; +}; +#pragma pack() + +struct cs_gem { + struct radeon_cs base; + struct drm_radeon_cs2 cs; + struct drm_radeon_cs_chunk chunks[2]; + unsigned nrelocs; + uint32_t *relocs; +}; + +static struct radeon_cs *cs_create(struct radeon_cs_manager *csm, + uint32_t ndw) +{ + struct cs_gem *csg; + + /* max cmd buffer size is 64Kb */ + if (ndw > (64 * 1024 / 4)) { + return NULL; + } + csg = (struct cs_gem*)calloc(1, sizeof(struct cs_gem)); + if (csg == NULL) { + return NULL; + } + csg->base.csm = csm; + csg->base.ndw = 64 * 1024 / 4; + csg->base.packets = (uint32_t*)calloc(1, 64 * 1024); + if (csg->base.packets == NULL) { + free(csg); + return NULL; + } + csg->base.relocs_total_size = 0; + csg->base.crelocs = 0; + csg->nrelocs = 4096 / (4 * 4) ; + csg->base.relocs = csg->relocs = (uint32_t*)calloc(1, 4096); + if (csg->relocs == NULL) { + free(csg->base.packets); + free(csg); + return NULL; + } + csg->chunks[0].chunk_id = RADEON_CHUNK_ID_IB; + csg->chunks[0].length_dw = 0; + csg->chunks[0].chunk_data = (uint64_t)(intptr_t)csg->base.packets; + csg->chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS; + csg->chunks[1].length_dw = 0; + csg->chunks[1].chunk_data = (uint64_t)(intptr_t)csg->relocs; + return (struct radeon_cs*)csg; +} + +static int cs_write_dword(struct radeon_cs *cs, uint32_t dword) +{ + if (cs->cdw >= cs->ndw) { + uint32_t tmp, *ptr; + tmp = (cs->cdw + 1 + 0x3FF) & (~0x3FF); + ptr = (uint32_t*)realloc(cs->packets, 4 * tmp); + if (ptr == NULL) { + return -ENOMEM; + } + cs->packets = ptr; + cs->ndw = tmp; + } + cs->packets[cs->cdw++] = dword; + if (cs->section) { + cs->section_cdw++; + } + return 0; +} + +static int cs_write_reloc(struct radeon_cs *cs, + struct radeon_bo *bo, + uint32_t soffset, + uint32_t eoffset, + uint32_t domains) +{ + struct cs_gem *csg = (struct cs_gem*)cs; + struct cs_reloc_gem *reloc; + unsigned i; + + /* check reloc window */ + if (eoffset > bo->size) { + return -EINVAL; + } + if (soffset > eoffset) { + return -EINVAL; + } + /* check if bo is already referenced */ + for(i = 0; i < cs->crelocs; i++) { + reloc = (struct cs_reloc_gem*)&csg->relocs[i * 4]; + + if (reloc->handle == bo->handle) { + /* update start offset and size */ + if (eoffset > reloc->eoffset) { + reloc->eoffset = eoffset; + } + if (soffset < reloc->soffset) { + reloc->soffset = soffset; + } + reloc->domains |= domains; + return 0; + } + } + /* add bo */ + if (csg->base.crelocs >= csg->nrelocs) { + uint32_t *tmp, size; + size = (csg->nrelocs * 4 * 4) + (4096 / (4 * 4)); + tmp = (uint32_t*)realloc(csg->relocs, size); + if (tmp == NULL) { + return -ENOMEM; + } + cs->relocs = csg->relocs = tmp; + csg->nrelocs = size / (4 * 4); + } + reloc = (struct cs_reloc_gem*)&csg->relocs[csg->base.crelocs * 4]; + reloc->handle = bo->handle; + reloc->soffset = soffset; + reloc->eoffset = eoffset; + reloc->domains = domains; + cs->crelocs++; + radeon_bo_ref(bo); + return 0; +} + +static int cs_begin(struct radeon_cs *cs, + uint32_t ndw, + const char *file, + const char *func, + int line) +{ + if (cs->section) { + fprintf(stderr, "CS already in a section(%s,%s,%d)\n", + cs->section_file, cs->section_func, cs->section_line); + fprintf(stderr, "CS can't start section(%s,%s,%d)\n", + file, func, line); + return -EPIPE; + } + cs->section = 1; + cs->section_ndw = ndw; + cs->section_cdw = 0; + cs->section_file = file; + cs->section_func = func; + cs->section_line = line; + return 0; +} + +static int cs_end(struct radeon_cs *cs, + const char *file, + const char *func, + int line) + +{ + if (!cs->section) { + fprintf(stderr, "CS no section to end at (%s,%s,%d)\n", + file, func, line); + return -EPIPE; + } + cs->section = 0; + if (cs->section_ndw != cs->section_cdw) { + fprintf(stderr, "CS section size missmatch start at (%s,%s,%d)\n", + cs->section_file, cs->section_func, cs->section_line); + fprintf(stderr, "CS section end at (%s,%s,%d)\n", + file, func, line); + return -EPIPE; + } + return 0; +} + +static int cs_emit(struct radeon_cs *cs) +{ + return 0; +} + +static int cs_destroy(struct radeon_cs *cs) +{ + free(cs->relocs); + free(cs->packets); + free(cs); + return 0; +} + +static int cs_erase(struct radeon_cs *cs) +{ + cs->relocs_total_size = 0; + cs->relocs = NULL; + cs->crelocs = 0; + cs->cdw = 0; + cs->section = 0; + return 0; +} + +static int cs_need_flush(struct radeon_cs *cs) +{ + return (cs->relocs_total_size > (7*1024*1024)); +} + +struct radeon_cs_funcs radeon_cs_funcs = { + cs_create, + cs_write_dword, + cs_write_reloc, + cs_begin, + cs_end, + cs_emit, + cs_destroy, + cs_erase, + cs_need_flush +}; + +struct radeon_cs_manager *radeon_cs_manager_gem(int fd) +{ + struct radeon_cs_manager *csm; + + csm = (struct radeon_cs_manager*)calloc(1, + sizeof(struct radeon_cs_manager)); + if (csm == NULL) { + return NULL; + } + csm->funcs = &radeon_cs_funcs; + csm->fd = fd; + return csm; +} + +void radeon_cs_manager_gem_shutdown(struct radeon_cs_manager *csm) +{ + free(csm); +} -- cgit v1.2.3 From 751d024dd5c91831a8141810c0f40ecdb235e7ca Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Sun, 9 Nov 2008 18:45:43 +0100 Subject: libdrm-radeon: update libdrm-radeon to match current CS relocation structures --- libdrm/radeon/radeon_cs_gem.c | 162 +++++++++++++++++++++++++++--------------- 1 file changed, 106 insertions(+), 56 deletions(-) (limited to 'libdrm/radeon/radeon_cs_gem.c') diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c index 7ed5780b..00aa9086 100644 --- a/libdrm/radeon/radeon_cs_gem.c +++ b/libdrm/radeon/radeon_cs_gem.c @@ -2,20 +2,21 @@ * Copyright © 2008 Jérôme Glisse * All Rights Reserved. * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. * * The above copyright notice and this permission notice (including the @@ -24,22 +25,27 @@ */ /* * Authors: + * Aapo Tahkola + * Nicolai Haehnle * Jérôme Glisse */ #include #include +#include +#include #include "radeon_cs.h" #include "radeon_cs_gem.h" #include "radeon_bo_gem.h" #include "drm.h" +#include "xf86drm.h" #include "radeon_drm.h" #pragma pack(1) struct cs_reloc_gem { uint32_t handle; - uint32_t domains; - uint32_t soffset; - uint32_t eoffset; + uint32_t rdomain; + uint32_t wdomain; + uint32_t cnt; }; #pragma pack() @@ -49,6 +55,7 @@ struct cs_gem { struct drm_radeon_cs_chunk chunks[2]; unsigned nrelocs; uint32_t *relocs; + struct radeon_bo **relocs_bo; }; static struct radeon_cs *cs_create(struct radeon_cs_manager *csm, @@ -74,8 +81,16 @@ static struct radeon_cs *cs_create(struct radeon_cs_manager *csm, csg->base.relocs_total_size = 0; csg->base.crelocs = 0; csg->nrelocs = 4096 / (4 * 4) ; + csg->relocs_bo = (struct radeon_bo**)calloc(1, + csg->nrelocs*sizeof(void*)); + if (csg->relocs_bo == NULL) { + free(csg->base.packets); + free(csg); + return NULL; + } csg->base.relocs = csg->relocs = (uint32_t*)calloc(1, 4096); if (csg->relocs == NULL) { + free(csg->relocs_bo); free(csg->base.packets); free(csg); return NULL; @@ -91,6 +106,7 @@ static struct radeon_cs *cs_create(struct radeon_cs_manager *csm, static int cs_write_dword(struct radeon_cs *cs, uint32_t dword) { + struct cs_gem *csg = (struct cs_gem*)cs; if (cs->cdw >= cs->ndw) { uint32_t tmp, *ptr; tmp = (cs->cdw + 1 + 0x3FF) & (~0x3FF); @@ -100,11 +116,10 @@ static int cs_write_dword(struct radeon_cs *cs, uint32_t dword) } cs->packets = ptr; cs->ndw = tmp; + csg->chunks[0].chunk_data = (uint64_t)(intptr_t)csg->base.packets; } cs->packets[cs->cdw++] = dword; - if (cs->section) { - cs->section_cdw++; - } + csg->chunks[0].length_dw += 1; return 0; } @@ -116,6 +131,7 @@ static int cs_write_reloc(struct radeon_cs *cs, { struct cs_gem *csg = (struct cs_gem*)cs; struct cs_reloc_gem *reloc; + uint32_t idx; unsigned i; /* check reloc window */ @@ -127,38 +143,73 @@ static int cs_write_reloc(struct radeon_cs *cs, } /* check if bo is already referenced */ for(i = 0; i < cs->crelocs; i++) { - reloc = (struct cs_reloc_gem*)&csg->relocs[i * 4]; + idx = i * 4; + reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; if (reloc->handle == bo->handle) { /* update start offset and size */ - if (eoffset > reloc->eoffset) { - reloc->eoffset = eoffset; + switch (bo->domains) { + case RADEON_GEM_DOMAIN_VRAM: + reloc->rdomain = 0; + reloc->wdomain = RADEON_GEM_DOMAIN_VRAM; + break; + case RADEON_GEM_DOMAIN_GTT: + reloc->rdomain = RADEON_GEM_DOMAIN_GTT; + reloc->wdomain = 0; + break; + default: + exit(0); + break; } - if (soffset < reloc->soffset) { - reloc->soffset = soffset; - } - reloc->domains |= domains; + reloc->cnt++; + cs_write_dword(cs, 0xc0001000); + cs_write_dword(cs, idx); return 0; } } /* add bo */ if (csg->base.crelocs >= csg->nrelocs) { uint32_t *tmp, size; - size = (csg->nrelocs * 4 * 4) + (4096 / (4 * 4)); + size = ((csg->nrelocs + 1) * sizeof(struct radeon_bo*)); + tmp = (uint32_t*)realloc(csg->relocs_bo, size); + if (tmp == NULL) { + return -ENOMEM; + } + csg->relocs_bo = (struct radeon_bo**)tmp; + size = ((csg->nrelocs + 1) * 4 * 4); tmp = (uint32_t*)realloc(csg->relocs, size); if (tmp == NULL) { return -ENOMEM; } cs->relocs = csg->relocs = tmp; - csg->nrelocs = size / (4 * 4); + csg->nrelocs += 1; + csg->chunks[1].chunk_data = (uint64_t)(intptr_t)csg->relocs; } - reloc = (struct cs_reloc_gem*)&csg->relocs[csg->base.crelocs * 4]; + csg->relocs_bo[csg->base.crelocs] = bo; + idx = (csg->base.crelocs++) * 4; + reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; reloc->handle = bo->handle; - reloc->soffset = soffset; - reloc->eoffset = eoffset; - reloc->domains = domains; - cs->crelocs++; + reloc->rdomain = bo->domains; + reloc->wdomain = bo->domains; + switch (bo->domains) { + case RADEON_GEM_DOMAIN_VRAM: + reloc->rdomain = 0; + reloc->wdomain = RADEON_GEM_DOMAIN_VRAM; + break; + case RADEON_GEM_DOMAIN_GTT: + reloc->rdomain = RADEON_GEM_DOMAIN_GTT; + reloc->wdomain = 0; + break; + default: + exit(0); + break; + } + reloc->cnt = 1; + csg->chunks[1].length_dw += 4; radeon_bo_ref(bo); + cs->relocs_total_size += bo->size; + cs_write_dword(cs, 0xc0001000); + cs_write_dword(cs, idx); return 0; } @@ -168,19 +219,6 @@ static int cs_begin(struct radeon_cs *cs, const char *func, int line) { - if (cs->section) { - fprintf(stderr, "CS already in a section(%s,%s,%d)\n", - cs->section_file, cs->section_func, cs->section_line); - fprintf(stderr, "CS can't start section(%s,%s,%d)\n", - file, func, line); - return -EPIPE; - } - cs->section = 1; - cs->section_ndw = ndw; - cs->section_cdw = 0; - cs->section_file = file; - cs->section_func = func; - cs->section_line = line; return 0; } @@ -190,29 +228,38 @@ static int cs_end(struct radeon_cs *cs, int line) { - if (!cs->section) { - fprintf(stderr, "CS no section to end at (%s,%s,%d)\n", - file, func, line); - return -EPIPE; - } cs->section = 0; - if (cs->section_ndw != cs->section_cdw) { - fprintf(stderr, "CS section size missmatch start at (%s,%s,%d)\n", - cs->section_file, cs->section_func, cs->section_line); - fprintf(stderr, "CS section end at (%s,%s,%d)\n", - file, func, line); - return -EPIPE; - } return 0; } static int cs_emit(struct radeon_cs *cs) { + struct cs_gem *csg = (struct cs_gem*)cs; + uint64_t chunk_array[2]; + int r; + + chunk_array[0] = (uint64_t)(intptr_t)&csg->chunks[0]; + chunk_array[1] = (uint64_t)(intptr_t)&csg->chunks[1]; + + csg->cs.num_chunks = 2; + csg->cs.chunks = (uint64_t)(intptr_t)chunk_array; + + r = drmCommandWriteRead(cs->csm->fd, DRM_RADEON_CS2, + &csg->cs, sizeof(struct drm_radeon_cs2)); + if (r) { + return r; + } + for(i = 0; i < cs->crelocs; i++) { + radeon_bo_unref(csg->relocs_bo[i]); + } return 0; } static int cs_destroy(struct radeon_cs *cs) { + struct cs_gem *csg = (struct cs_gem*)cs; + + free(csg->relocs_bo); free(cs->relocs); free(cs->packets); free(cs); @@ -221,17 +268,20 @@ static int cs_destroy(struct radeon_cs *cs) static int cs_erase(struct radeon_cs *cs) { + struct cs_gem *csg = (struct cs_gem*)cs; + cs->relocs_total_size = 0; - cs->relocs = NULL; - cs->crelocs = 0; cs->cdw = 0; cs->section = 0; + cs->crelocs = 0; + csg->chunks[0].length_dw = 0; + csg->chunks[1].length_dw = 0; return 0; } static int cs_need_flush(struct radeon_cs *cs) { - return (cs->relocs_total_size > (7*1024*1024)); + return (cs->relocs_total_size > (16*1024*1024)); } struct radeon_cs_funcs radeon_cs_funcs = { -- cgit v1.2.3 From 72997fb3726b99b99c44e96e59abd8c70abbd8be Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Mon, 10 Nov 2008 22:18:22 +0100 Subject: libdrm-radeon: be verbose on bo failure and cleanup cs a bit --- libdrm/radeon/radeon_cs_gem.c | 75 +++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 39 deletions(-) (limited to 'libdrm/radeon/radeon_cs_gem.c') diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c index 00aa9086..6be1728f 100644 --- a/libdrm/radeon/radeon_cs_gem.c +++ b/libdrm/radeon/radeon_cs_gem.c @@ -58,8 +58,8 @@ struct cs_gem { struct radeon_bo **relocs_bo; }; -static struct radeon_cs *cs_create(struct radeon_cs_manager *csm, - uint32_t ndw) +static struct radeon_cs *cs_gem_create(struct radeon_cs_manager *csm, + uint32_t ndw) { struct cs_gem *csg; @@ -104,7 +104,7 @@ static struct radeon_cs *cs_create(struct radeon_cs_manager *csm, return (struct radeon_cs*)csg; } -static int cs_write_dword(struct radeon_cs *cs, uint32_t dword) +static int cs_gem_write_dword(struct radeon_cs *cs, uint32_t dword) { struct cs_gem *csg = (struct cs_gem*)cs; if (cs->cdw >= cs->ndw) { @@ -123,11 +123,11 @@ static int cs_write_dword(struct radeon_cs *cs, uint32_t dword) return 0; } -static int cs_write_reloc(struct radeon_cs *cs, - struct radeon_bo *bo, - uint32_t soffset, - uint32_t eoffset, - uint32_t domains) +static int cs_gem_write_reloc(struct radeon_cs *cs, + struct radeon_bo *bo, + uint32_t soffset, + uint32_t eoffset, + uint32_t domains) { struct cs_gem *csg = (struct cs_gem*)cs; struct cs_reloc_gem *reloc; @@ -162,8 +162,8 @@ static int cs_write_reloc(struct radeon_cs *cs, break; } reloc->cnt++; - cs_write_dword(cs, 0xc0001000); - cs_write_dword(cs, idx); + cs_gem_write_dword(cs, 0xc0001000); + cs_gem_write_dword(cs, idx); return 0; } } @@ -208,31 +208,31 @@ static int cs_write_reloc(struct radeon_cs *cs, csg->chunks[1].length_dw += 4; radeon_bo_ref(bo); cs->relocs_total_size += bo->size; - cs_write_dword(cs, 0xc0001000); - cs_write_dword(cs, idx); + cs_gem_write_dword(cs, 0xc0001000); + cs_gem_write_dword(cs, idx); return 0; } -static int cs_begin(struct radeon_cs *cs, - uint32_t ndw, - const char *file, - const char *func, - int line) +static int cs_gem_begin(struct radeon_cs *cs, + uint32_t ndw, + const char *file, + const char *func, + int line) { return 0; } -static int cs_end(struct radeon_cs *cs, - const char *file, - const char *func, - int line) +static int cs_gem_end(struct radeon_cs *cs, + const char *file, + const char *func, + int line) { cs->section = 0; return 0; } -static int cs_emit(struct radeon_cs *cs) +static int cs_gem_emit(struct radeon_cs *cs) { struct cs_gem *csg = (struct cs_gem*)cs; uint64_t chunk_array[2]; @@ -249,13 +249,10 @@ static int cs_emit(struct radeon_cs *cs) if (r) { return r; } - for(i = 0; i < cs->crelocs; i++) { - radeon_bo_unref(csg->relocs_bo[i]); - } return 0; } -static int cs_destroy(struct radeon_cs *cs) +static int cs_gem_destroy(struct radeon_cs *cs) { struct cs_gem *csg = (struct cs_gem*)cs; @@ -266,7 +263,7 @@ static int cs_destroy(struct radeon_cs *cs) return 0; } -static int cs_erase(struct radeon_cs *cs) +static int cs_gem_erase(struct radeon_cs *cs) { struct cs_gem *csg = (struct cs_gem*)cs; @@ -279,21 +276,21 @@ static int cs_erase(struct radeon_cs *cs) return 0; } -static int cs_need_flush(struct radeon_cs *cs) +static int cs_gem_need_flush(struct radeon_cs *cs) { return (cs->relocs_total_size > (16*1024*1024)); } -struct radeon_cs_funcs radeon_cs_funcs = { - cs_create, - cs_write_dword, - cs_write_reloc, - cs_begin, - cs_end, - cs_emit, - cs_destroy, - cs_erase, - cs_need_flush +static struct radeon_cs_funcs radeon_cs_gem_funcs = { + cs_gem_create, + cs_gem_write_dword, + cs_gem_write_reloc, + cs_gem_begin, + cs_gem_end, + cs_gem_emit, + cs_gem_destroy, + cs_gem_erase, + cs_gem_need_flush }; struct radeon_cs_manager *radeon_cs_manager_gem(int fd) @@ -305,7 +302,7 @@ struct radeon_cs_manager *radeon_cs_manager_gem(int fd) if (csm == NULL) { return NULL; } - csm->funcs = &radeon_cs_funcs; + csm->funcs = &radeon_cs_gem_funcs; csm->fd = fd; return csm; } -- cgit v1.2.3 From a7457915f5775137436f3b16a640eb8bd6424ca6 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 12 Nov 2008 15:56:40 +0100 Subject: radeon+libdrm-radeon: change relocation informations Relocation now consist of the following informations (in this order) : handle buffer object handle identifier start_offset start offset of first data of the buffer object used by the cs end_offset end offset of last data of the buffer object used by the cs read_domain read domain (either VRAM, or GTT as GPU is invalid for CS) write_domain write domain (either VRAM, or GTT as GPU is invalid for CS) flags flags used for further optimization (like discard previous buffer content or forget buffer content after cs which can help in avoiding moving content in or out) --- libdrm/radeon/radeon_cs_gem.c | 103 ++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 44 deletions(-) (limited to 'libdrm/radeon/radeon_cs_gem.c') diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c index 6be1728f..f9c9fabb 100644 --- a/libdrm/radeon/radeon_cs_gem.c +++ b/libdrm/radeon/radeon_cs_gem.c @@ -43,9 +43,11 @@ #pragma pack(1) struct cs_reloc_gem { uint32_t handle; - uint32_t rdomain; - uint32_t wdomain; - uint32_t cnt; + uint32_t start_offset; + uint32_t end_offset; + uint32_t read_domain; + uint32_t write_domain; + uint32_t flags; }; #pragma pack() @@ -125,50 +127,74 @@ static int cs_gem_write_dword(struct radeon_cs *cs, uint32_t dword) static int cs_gem_write_reloc(struct radeon_cs *cs, struct radeon_bo *bo, - uint32_t soffset, - uint32_t eoffset, - uint32_t domains) + uint32_t start_offset, + uint32_t end_offset, + uint32_t read_domain, + uint32_t write_domain, + uint32_t flags) { struct cs_gem *csg = (struct cs_gem*)cs; struct cs_reloc_gem *reloc; uint32_t idx; unsigned i; + /* check domains */ + if ((read_domain && write_domain) || (!read_domain && !write_domain)) { + /* in one CS a bo can only be in read or write domain but not + * in read & write domain at the same sime + */ + return -EINVAL; + } + if (read_domain == RADEON_GEM_DOMAIN_CPU) { + return -EINVAL; + } + if (write_domain == RADEON_GEM_DOMAIN_CPU) { + return -EINVAL; + } /* check reloc window */ - if (eoffset > bo->size) { + if (end_offset > bo->size) { return -EINVAL; } - if (soffset > eoffset) { + if (start_offset > end_offset) { return -EINVAL; } /* check if bo is already referenced */ for(i = 0; i < cs->crelocs; i++) { - idx = i * 4; + idx = i * 6; reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; - if (reloc->handle == bo->handle) { - /* update start offset and size */ - switch (bo->domains) { - case RADEON_GEM_DOMAIN_VRAM: - reloc->rdomain = 0; - reloc->wdomain = RADEON_GEM_DOMAIN_VRAM; - break; - case RADEON_GEM_DOMAIN_GTT: - reloc->rdomain = RADEON_GEM_DOMAIN_GTT; - reloc->wdomain = 0; - break; - default: - exit(0); - break; + /* Check domains must be in read or write. As we check already + * checked that in argument one of the read or write domain was + * set we only need to check that if previous reloc as the read + * domain set then the read_domain should also be set for this + * new relocation. + */ + if (reloc->read_domain && !read_domain) { + return -EINVAL; + } + if (reloc->write_domain && !write_domain) { + return -EINVAL; + } + reloc->read_domain |= read_domain; + reloc->write_domain |= write_domain; + /* update start and end offset */ + if (start_offset < reloc->start_offset) { + reloc->start_offset = start_offset; } - reloc->cnt++; + if (end_offset > reloc->end_offset) { + reloc->end_offset = end_offset; + } + /* update flags */ + reloc->flags |= (flags & reloc->flags); + /* write relocation packet */ cs_gem_write_dword(cs, 0xc0001000); cs_gem_write_dword(cs, idx); return 0; } } - /* add bo */ + /* new relocation */ if (csg->base.crelocs >= csg->nrelocs) { + /* allocate more memory (TODO: should use a slab allocatore maybe) */ uint32_t *tmp, size; size = ((csg->nrelocs + 1) * sizeof(struct radeon_bo*)); tmp = (uint32_t*)realloc(csg->relocs_bo, size); @@ -176,7 +202,7 @@ static int cs_gem_write_reloc(struct radeon_cs *cs, return -ENOMEM; } csg->relocs_bo = (struct radeon_bo**)tmp; - size = ((csg->nrelocs + 1) * 4 * 4); + size = ((csg->nrelocs + 1) * 6 * 4); tmp = (uint32_t*)realloc(csg->relocs, size); if (tmp == NULL) { return -ENOMEM; @@ -186,26 +212,15 @@ static int cs_gem_write_reloc(struct radeon_cs *cs, csg->chunks[1].chunk_data = (uint64_t)(intptr_t)csg->relocs; } csg->relocs_bo[csg->base.crelocs] = bo; - idx = (csg->base.crelocs++) * 4; + idx = (csg->base.crelocs++) * 6; reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; reloc->handle = bo->handle; - reloc->rdomain = bo->domains; - reloc->wdomain = bo->domains; - switch (bo->domains) { - case RADEON_GEM_DOMAIN_VRAM: - reloc->rdomain = 0; - reloc->wdomain = RADEON_GEM_DOMAIN_VRAM; - break; - case RADEON_GEM_DOMAIN_GTT: - reloc->rdomain = RADEON_GEM_DOMAIN_GTT; - reloc->wdomain = 0; - break; - default: - exit(0); - break; - } - reloc->cnt = 1; - csg->chunks[1].length_dw += 4; + reloc->start_offset = start_offset; + reloc->end_offset = end_offset; + reloc->read_domain = read_domain; + reloc->write_domain = write_domain; + reloc->flags = flags; + csg->chunks[1].length_dw += 6; radeon_bo_ref(bo); cs->relocs_total_size += bo->size; cs_gem_write_dword(cs, 0xc0001000); -- cgit v1.2.3 From 080a45624b2b0ac9e0173f5b93760ae018394dd1 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 14 Nov 2008 12:13:53 +0100 Subject: libdrm-radeon: unreference buffer once cs stream is submited or on cs clean BO are referenced once by reloc to make sure that they not destroyed before we get a chance to flush the cmd stream, so we need to unreference them once in cs submit or cs erase if cs i never submitted so bo can be destructed. --- libdrm/radeon/radeon_cs_gem.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'libdrm/radeon/radeon_cs_gem.c') diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c index f9c9fabb..9488f81c 100644 --- a/libdrm/radeon/radeon_cs_gem.c +++ b/libdrm/radeon/radeon_cs_gem.c @@ -251,7 +251,7 @@ static int cs_gem_emit(struct radeon_cs *cs) { struct cs_gem *csg = (struct cs_gem*)cs; uint64_t chunk_array[2]; - int r; + int r, i; chunk_array[0] = (uint64_t)(intptr_t)&csg->chunks[0]; chunk_array[1] = (uint64_t)(intptr_t)&csg->chunks[1]; @@ -261,10 +261,11 @@ static int cs_gem_emit(struct radeon_cs *cs) r = drmCommandWriteRead(cs->csm->fd, DRM_RADEON_CS2, &csg->cs, sizeof(struct drm_radeon_cs2)); - if (r) { - return r; + for (i = 0; i < csg->base.crelocs; i++) { + radeon_bo_unref(csg->relocs_bo[i]); + csg->relocs_bo[i] = NULL; } - return 0; + return r; } static int cs_gem_destroy(struct radeon_cs *cs) @@ -281,7 +282,16 @@ static int cs_gem_destroy(struct radeon_cs *cs) static int cs_gem_erase(struct radeon_cs *cs) { struct cs_gem *csg = (struct cs_gem*)cs; + int i; + if (csg->relocs_bo) { + for (i = 0; i < csg->base.crelocs; i++) { + if (csg->relocs_bo[i]) { + radeon_bo_unref(csg->relocs_bo[i]); + csg->relocs_bo[i] = NULL; + } + } + } cs->relocs_total_size = 0; cs->cdw = 0; cs->section = 0; -- cgit v1.2.3 From 5ae79e7edd819b84d9e447a2ab9b995a862ac3a7 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Sat, 15 Nov 2008 10:38:44 +0100 Subject: libdrm-radeon: unref return current BO ptr to reflect BO destruction --- libdrm/radeon/radeon_cs_gem.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'libdrm/radeon/radeon_cs_gem.c') diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c index 9488f81c..91489dff 100644 --- a/libdrm/radeon/radeon_cs_gem.c +++ b/libdrm/radeon/radeon_cs_gem.c @@ -251,7 +251,8 @@ static int cs_gem_emit(struct radeon_cs *cs) { struct cs_gem *csg = (struct cs_gem*)cs; uint64_t chunk_array[2]; - int r, i; + unsigned i; + int r; chunk_array[0] = (uint64_t)(intptr_t)&csg->chunks[0]; chunk_array[1] = (uint64_t)(intptr_t)&csg->chunks[1]; @@ -282,7 +283,7 @@ static int cs_gem_destroy(struct radeon_cs *cs) static int cs_gem_erase(struct radeon_cs *cs) { struct cs_gem *csg = (struct cs_gem*)cs; - int i; + unsigned i; if (csg->relocs_bo) { for (i = 0; i < csg->base.crelocs; i++) { @@ -318,7 +319,7 @@ static struct radeon_cs_funcs radeon_cs_gem_funcs = { cs_gem_need_flush }; -struct radeon_cs_manager *radeon_cs_manager_gem(int fd) +struct radeon_cs_manager *radeon_cs_manager_gem_ctor(int fd) { struct radeon_cs_manager *csm; @@ -332,7 +333,7 @@ struct radeon_cs_manager *radeon_cs_manager_gem(int fd) return csm; } -void radeon_cs_manager_gem_shutdown(struct radeon_cs_manager *csm) +void radeon_cs_manager_gem_dtor(struct radeon_cs_manager *csm) { free(csm); } -- cgit v1.2.3 From c0ba14fd90e7495d5634c1ce0a9fb5be26230010 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Sun, 16 Nov 2008 18:04:43 +0100 Subject: libdrm-radeon: add print callback to cs & small fixes --- libdrm/radeon/radeon_cs_gem.c | 103 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) (limited to 'libdrm/radeon/radeon_cs_gem.c') diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c index 91489dff..319d1b9e 100644 --- a/libdrm/radeon/radeon_cs_gem.c +++ b/libdrm/radeon/radeon_cs_gem.c @@ -254,6 +254,8 @@ static int cs_gem_emit(struct radeon_cs *cs) unsigned i; int r; + csg->chunks[0].length_dw = cs->cdw; + chunk_array[0] = (uint64_t)(intptr_t)&csg->chunks[0]; chunk_array[1] = (uint64_t)(intptr_t)&csg->chunks[1]; @@ -304,7 +306,103 @@ static int cs_gem_erase(struct radeon_cs *cs) static int cs_gem_need_flush(struct radeon_cs *cs) { - return (cs->relocs_total_size > (16*1024*1024)); + return (cs->relocs_total_size > (32*1024*1024)); +} + +#define PACKET_TYPE0 0 +#define PACKET_TYPE1 1 +#define PACKET_TYPE2 2 +#define PACKET_TYPE3 3 + +#define PACKET3_NOP 0x10 +#define PACKET3_SET_SCISSORS 0x1E +#define PACKET3_3D_DRAW_VBUF 0x28 +#define PACKET3_3D_DRAW_IMMD 0x29 +#define PACKET3_3D_DRAW_INDX 0x2A +#define PACKET3_3D_LOAD_VBPNTR 0x2F +#define PACKET3_INDX_BUFFER 0x33 +#define PACKET3_3D_DRAW_VBUF_2 0x34 +#define PACKET3_3D_DRAW_IMMD_2 0x35 +#define PACKET3_3D_DRAW_INDX_2 0x36 + +#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) +#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) +#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2) +#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) +#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) + +static void cs_gem_print(struct radeon_cs *cs, FILE *file) +{ + unsigned opcode; + unsigned reg; + unsigned cnt; + int i, j; + + for (i = 0; i < cs->cdw;) { + cnt = CP_PACKET_GET_COUNT(cs->packets[i]); + switch (CP_PACKET_GET_TYPE(cs->packets[i])) { + case PACKET_TYPE0: + fprintf(file, "Pkt0 at %d (%d dwords):\n", i, cnt + 1); + reg = CP_PACKET0_GET_REG(cs->packets[i]); + if (CP_PACKET0_GET_ONE_REG_WR(cs->packets[i++])) { + for (j = 0; j <= cnt; j++) { + fprintf(file, " 0x%08X -> 0x%04X\n", + cs->packets[i++], reg); + } + } else { + for (j = 0; j <= cnt; j++) { + fprintf(file, " 0x%08X -> 0x%04X\n", + cs->packets[i++], reg); + reg += 4; + } + } + break; + case PACKET_TYPE3: + fprintf(file, "Pkt3 at %d :\n", i); + opcode = CP_PACKET3_GET_OPCODE(cs->packets[i++]); + switch (opcode) { + case PACKET3_NOP: + fprintf(file, " PACKET3_NOP:\n"); + break; + case PACKET3_3D_DRAW_VBUF: + fprintf(file, " PACKET3_3D_DRAW_VBUF:\n"); + break; + case PACKET3_3D_DRAW_IMMD: + fprintf(file, " PACKET3_3D_DRAW_IMMD:\n"); + break; + case PACKET3_3D_DRAW_INDX: + fprintf(file, " PACKET3_3D_DRAW_INDX:\n"); + break; + case PACKET3_3D_LOAD_VBPNTR: + fprintf(file, " PACKET3_3D_LOAD_VBPNTR:\n"); + break; + case PACKET3_INDX_BUFFER: + fprintf(file, " PACKET3_INDX_BUFFER:\n"); + break; + case PACKET3_3D_DRAW_VBUF_2: + fprintf(file, " PACKET3_3D_DRAW_VBUF_2:\n"); + break; + case PACKET3_3D_DRAW_IMMD_2: + fprintf(file, " PACKET3_3D_DRAW_IMMD_2:\n"); + break; + case PACKET3_3D_DRAW_INDX_2: + fprintf(file, " PACKET3_3D_DRAW_INDX_2:\n"); + break; + default: + fprintf(file, "Unknow opcode 0x%02X at %d\n", opcode, i); + return; + } + for (j = 0; j <= cnt; j++) { + fprintf(file, " 0x%08X\n", cs->packets[i++]); + } + break; + case PACKET_TYPE1: + case PACKET_TYPE2: + default: + fprintf(file, "Unknow packet 0x%08X at %d\n", cs->packets[i], i); + return; + } + } } static struct radeon_cs_funcs radeon_cs_gem_funcs = { @@ -316,7 +414,8 @@ static struct radeon_cs_funcs radeon_cs_gem_funcs = { cs_gem_emit, cs_gem_destroy, cs_gem_erase, - cs_gem_need_flush + cs_gem_need_flush, + cs_gem_print }; struct radeon_cs_manager *radeon_cs_manager_gem_ctor(int fd) -- cgit v1.2.3