On 10/04/2016 09:18 PM, Nicolai Hähnle wrote: > You may want to add a "based on" in the copyright header also to > radv_radeon_winsys.h.
One thing I did notice with the new headers in general is using pragma's over usual header guards.. You guys likely did this for rapid dev but I think we should fix them to be guards before merge. Cheers, Edward. > > Apart from that, I'm fine with merging this patch, though I only skimmed > it. > > Cheers, > Nicolai > > On 04.10.2016 03:48, Dave Airlie wrote: >> From: Dave Airlie <airl...@redhat.com> >> >> This just brings these files into the tree, it doesn't integrate >> them with the build system. >> >> The radv winsys is based on the gallium one with some changes, >> due to how command buffers are built and lack of flushing behaviour. >> >> Authors: Bas Nieuwenhuizen and Dave Airlie >> Signed-off-by: Dave Airlie <airl...@redhat.com> >> --- >> src/amd/vulkan/radv_radeon_winsys.h | 332 +++++++++ >> src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c | 297 ++++++++ >> src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.h | 50 ++ >> src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.c | 778 >> +++++++++++++++++++++ >> src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.h | 52 ++ >> src/amd/vulkan/winsys/amdgpu/radv_amdgpu_surface.c | 523 ++++++++++++++ >> src/amd/vulkan/winsys/amdgpu/radv_amdgpu_surface.h | 29 + >> src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.c | 359 ++++++++++ >> src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.h | 32 + >> .../winsys/amdgpu/radv_amdgpu_winsys_public.h | 30 + >> 10 files changed, 2482 insertions(+) >> create mode 100644 src/amd/vulkan/radv_radeon_winsys.h >> create mode 100644 src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c >> create mode 100644 src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.h >> create mode 100644 src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.c >> create mode 100644 src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.h >> create mode 100644 src/amd/vulkan/winsys/amdgpu/radv_amdgpu_surface.c >> create mode 100644 src/amd/vulkan/winsys/amdgpu/radv_amdgpu_surface.h >> create mode 100644 src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.c >> create mode 100644 src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.h >> create mode 100644 >> src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys_public.h >> >> diff --git a/src/amd/vulkan/radv_radeon_winsys.h >> b/src/amd/vulkan/radv_radeon_winsys.h >> new file mode 100644 >> index 0000000..1297583 >> --- /dev/null >> +++ b/src/amd/vulkan/radv_radeon_winsys.h >> @@ -0,0 +1,332 @@ >> +/* >> + * Copyright © 2016 Red Hat. >> + * Copyright © 2016 Bas Nieuwenhuizen >> + * >> + * 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, >> sublicense, >> + * 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 above copyright notice and this permission notice (including >> the next >> + * paragraph) shall be included in all copies or substantial portions >> of the >> + * Software. >> + * >> + * 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 NONINFRINGEMENT. IN NO EVENT >> SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS 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. >> + */ >> +#pragma once >> + >> +#include <stdint.h> >> +#include <stdbool.h> >> +#include <stdlib.h> >> +#include "main/macros.h" >> +#include "ac_radeon_winsys.h" >> + >> +#define FREE(x) free(x) >> + >> +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_CPU_ACCESS = (1 << 1), >> + RADEON_FLAG_NO_CPU_ACCESS = (1 << 2), >> +}; >> + >> +enum radeon_bo_usage { /* bitfield */ >> + RADEON_USAGE_READ = 2, >> + RADEON_USAGE_WRITE = 4, >> + RADEON_USAGE_READWRITE = RADEON_USAGE_READ | RADEON_USAGE_WRITE >> +}; >> + >> +enum ring_type { >> + RING_GFX = 0, >> + RING_COMPUTE, >> + RING_DMA, >> + RING_UVD, >> + RING_VCE, >> + RING_LAST, >> +}; >> + >> +struct radeon_winsys_cs { >> + unsigned cdw; /* Number of used dwords. */ >> + unsigned max_dw; /* Maximum number of dwords. */ >> + uint32_t *buf; /* The base pointer of the chunk. */ >> +}; >> + >> +struct radeon_info { >> + /* PCI info: domain:bus:dev:func */ >> + uint32_t pci_domain; >> + uint32_t pci_bus; >> + uint32_t pci_dev; >> + uint32_t pci_func; >> + >> + /* Device info. */ >> + uint32_t pci_id; >> + enum radeon_family family; >> + const char *name; >> + enum chip_class chip_class; >> + uint32_t gart_page_size; >> + uint64_t gart_size; >> + uint64_t vram_size; >> + bool has_dedicated_vram; >> + bool has_virtual_memory; >> + bool gfx_ib_pad_with_type2; >> + bool has_sdma; >> + bool has_uvd; >> + uint32_t vce_fw_version; >> + uint32_t vce_harvest_config; >> + uint32_t clock_crystal_freq; >> + >> + /* Kernel info. */ >> + uint32_t drm_major; /* version */ >> + uint32_t drm_minor; >> + uint32_t drm_patchlevel; >> + bool has_userptr; >> + >> + /* Shader cores. */ >> + uint32_t r600_max_quad_pipes; /* wave size / >> 16 */ >> + uint32_t max_shader_clock; >> + uint32_t num_good_compute_units; >> + uint32_t max_se; /* shader engines */ >> + uint32_t max_sh_per_se; /* shader arrays per >> shader engine */ >> + >> + /* Render backends (color + depth blocks). */ >> + uint32_t r300_num_gb_pipes; >> + uint32_t r300_num_z_pipes; >> + uint32_t r600_gb_backend_map; /* R600 harvest >> config */ >> + bool r600_gb_backend_map_valid; >> + uint32_t r600_num_banks; >> + uint32_t num_render_backends; >> + uint32_t num_tile_pipes; /* pipe count from >> PIPE_CONFIG */ >> + uint32_t pipe_interleave_bytes; >> + uint32_t enabled_rb_mask; /* GCN harvest >> config */ >> + >> + /* Tile modes. */ >> + uint32_t si_tile_mode_array[32]; >> + uint32_t cik_macrotile_mode_array[16]; >> +}; >> + >> +#define RADEON_SURF_MAX_LEVEL 32 >> + >> +#define RADEON_SURF_TYPE_MASK 0xFF >> +#define RADEON_SURF_TYPE_SHIFT 0 >> +#define RADEON_SURF_TYPE_1D 0 >> +#define RADEON_SURF_TYPE_2D 1 >> +#define RADEON_SURF_TYPE_3D 2 >> +#define RADEON_SURF_TYPE_CUBEMAP 3 >> +#define RADEON_SURF_TYPE_1D_ARRAY 4 >> +#define RADEON_SURF_TYPE_2D_ARRAY 5 >> +#define RADEON_SURF_MODE_MASK 0xFF >> +#define RADEON_SURF_MODE_SHIFT 8 >> +#define RADEON_SURF_MODE_LINEAR_ALIGNED 1 >> +#define RADEON_SURF_MODE_1D 2 >> +#define RADEON_SURF_MODE_2D 3 >> +#define RADEON_SURF_SCANOUT (1 << 16) >> +#define RADEON_SURF_ZBUFFER (1 << 17) >> +#define RADEON_SURF_SBUFFER (1 << 18) >> +#define RADEON_SURF_Z_OR_SBUFFER (RADEON_SURF_ZBUFFER >> | RADEON_SURF_SBUFFER) >> +#define RADEON_SURF_HAS_SBUFFER_MIPTREE (1 << 19) >> +#define RADEON_SURF_HAS_TILE_MODE_INDEX (1 << 20) >> +#define RADEON_SURF_FMASK (1 << 21) >> +#define RADEON_SURF_DISABLE_DCC (1 << 22) >> + >> +#define RADEON_SURF_GET(v, field) (((v) >> RADEON_SURF_ ## field ## >> _SHIFT) & RADEON_SURF_ ## field ## _MASK) >> +#define RADEON_SURF_SET(v, field) (((v) & RADEON_SURF_ ## field ## >> _MASK) << RADEON_SURF_ ## field ## _SHIFT) >> +#define RADEON_SURF_CLR(v, field) ((v) & ~(RADEON_SURF_ ## field ## >> _MASK << RADEON_SURF_ ## field ## _SHIFT)) >> + >> +struct radeon_surf_level { >> + uint64_t offset; >> + uint64_t slice_size; >> + uint32_t npix_x; >> + uint32_t npix_y; >> + uint32_t npix_z; >> + uint32_t nblk_x; >> + uint32_t nblk_y; >> + uint32_t nblk_z; >> + uint32_t pitch_bytes; >> + uint32_t mode; >> + uint64_t dcc_offset; >> + uint64_t dcc_fast_clear_size; >> + bool dcc_enabled; >> +}; >> + >> + >> +/* surface defintions from the winsys */ >> +struct radeon_surf { >> + /* These are inputs to the calculator. */ >> + uint32_t npix_x; >> + uint32_t npix_y; >> + uint32_t npix_z; >> + uint32_t blk_w; >> + uint32_t blk_h; >> + uint32_t blk_d; >> + uint32_t array_size; >> + uint32_t last_level; >> + uint32_t bpe; >> + uint32_t nsamples; >> + uint32_t flags; >> + >> + /* These are return values. Some of them can be set by the >> caller, but >> + * they will be treated as hints (e.g. bankw, bankh) and might be >> + * changed by the calculator. >> + */ >> + uint64_t bo_size; >> + uint64_t bo_alignment; >> + /* This applies to EG and later. */ >> + uint32_t bankw; >> + uint32_t bankh; >> + uint32_t mtilea; >> + uint32_t tile_split; >> + uint32_t stencil_tile_split; >> + uint64_t stencil_offset; >> + struct radeon_surf_level level[RADEON_SURF_MAX_LEVEL]; >> + struct radeon_surf_level stencil_level[RADEON_SURF_MAX_LEVEL]; >> + uint32_t tiling_index[RADEON_SURF_MAX_LEVEL]; >> + uint32_t >> stencil_tiling_index[RADEON_SURF_MAX_LEVEL]; >> + uint32_t pipe_config; >> + uint32_t num_banks; >> + uint32_t macro_tile_index; >> + uint32_t micro_tile_mode; /* displayable, >> thin, depth, rotated */ >> + >> + /* Whether the depth miptree or stencil miptree as used by the DB >> are >> + * adjusted from their TC compatible form to ensure depth/stencil >> + * compatibility. If either is true, the corresponding plane >> cannot be >> + * sampled from. >> + */ >> + bool depth_adjusted; >> + bool stencil_adjusted; >> + >> + uint64_t dcc_size; >> + uint64_t dcc_alignment; >> +}; >> + >> +enum radeon_bo_layout { >> + RADEON_LAYOUT_LINEAR = 0, >> + RADEON_LAYOUT_TILED, >> + RADEON_LAYOUT_SQUARETILED, >> + >> + RADEON_LAYOUT_UNKNOWN >> +}; >> + >> +/* Tiling info for display code, DRI sharing, and other data. */ >> +struct radeon_bo_metadata { >> + /* Tiling flags describing the texture layout for display code >> + * and DRI sharing. >> + */ >> + enum radeon_bo_layout microtile; >> + enum radeon_bo_layout macrotile; >> + unsigned pipe_config; >> + unsigned bankw; >> + unsigned bankh; >> + unsigned tile_split; >> + unsigned mtilea; >> + unsigned num_banks; >> + unsigned stride; >> + bool scanout; >> + >> + /* Additional metadata associated with the buffer, in bytes. >> + * The maximum size is 64 * 4. This is opaque for the winsys & >> kernel. >> + * Supported by amdgpu only. >> + */ >> + uint32_t size_metadata; >> + uint32_t metadata[64]; >> +}; >> + >> +struct radeon_winsys_bo; >> +struct radeon_winsys_fence; >> + >> +struct radeon_winsys { >> + void (*destroy)(struct radeon_winsys *ws); >> + >> + void (*query_info)(struct radeon_winsys *ws, >> + struct radeon_info *info); >> + >> + struct radeon_winsys_bo *(*buffer_create)(struct radeon_winsys *ws, >> + uint64_t size, >> + unsigned alignment, >> + enum radeon_bo_domain domain, >> + enum radeon_bo_flag flags); >> + >> + void (*buffer_destroy)(struct radeon_winsys_bo *bo); >> + void *(*buffer_map)(struct radeon_winsys_bo *bo); >> + >> + struct radeon_winsys_bo *(*buffer_from_fd)(struct radeon_winsys *ws, >> + int fd, >> + unsigned *stride, unsigned *offset); >> + >> + bool (*buffer_get_fd)(struct radeon_winsys *ws, >> + struct radeon_winsys_bo *bo, >> + int *fd); >> + >> + void (*buffer_unmap)(struct radeon_winsys_bo *bo); >> + >> + uint64_t (*buffer_get_va)(struct radeon_winsys_bo *bo); >> + >> + void (*buffer_set_metadata)(struct radeon_winsys_bo *bo, >> + struct radeon_bo_metadata *md); >> + struct radeon_winsys_ctx *(*ctx_create)(struct radeon_winsys *ws); >> + void (*ctx_destroy)(struct radeon_winsys_ctx *ctx); >> + >> + bool (*ctx_wait_idle)(struct radeon_winsys_ctx *ctx); >> + >> + struct radeon_winsys_cs *(*cs_create)(struct radeon_winsys *ws, >> + enum ring_type ring_type); >> + >> + void (*cs_destroy)(struct radeon_winsys_cs *cs); >> + >> + void (*cs_reset)(struct radeon_winsys_cs *cs); >> + >> + bool (*cs_finalize)(struct radeon_winsys_cs *cs); >> + >> + void (*cs_grow)(struct radeon_winsys_cs * cs, size_t min_size); >> + >> + int (*cs_submit)(struct radeon_winsys_ctx *ctx, >> + struct radeon_winsys_cs **cs_array, >> + unsigned cs_count, >> + bool can_patch, >> + struct radeon_winsys_fence *fence); >> + >> + void (*cs_add_buffer)(struct radeon_winsys_cs *cs, >> + struct radeon_winsys_bo *bo, >> + uint8_t priority); >> + >> + void (*cs_execute_secondary)(struct radeon_winsys_cs *parent, >> + struct radeon_winsys_cs *child); >> + >> + int (*surface_init)(struct radeon_winsys *ws, >> + struct radeon_surf *surf); >> + >> + int (*surface_best)(struct radeon_winsys *ws, >> + struct radeon_surf *surf); >> + >> + struct radeon_winsys_fence *(*create_fence)(); >> + void (*destroy_fence)(struct radeon_winsys_fence *fence); >> + bool (*fence_wait)(struct radeon_winsys *ws, >> + struct radeon_winsys_fence *fence, >> + bool absolute, >> + uint64_t timeout); >> +}; >> + >> +static inline void radeon_emit(struct radeon_winsys_cs *cs, uint32_t >> value) >> +{ >> + cs->buf[cs->cdw++] = value; >> +} >> + >> +static inline void radeon_emit_array(struct radeon_winsys_cs *cs, >> + const uint32_t *values, unsigned count) >> +{ >> + memcpy(cs->buf + cs->cdw, values, count * 4); >> + cs->cdw += count; >> +} >> + >> diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c >> b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c >> new file mode 100644 >> index 0000000..b8ce3ce >> --- /dev/null >> +++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c >> @@ -0,0 +1,297 @@ >> +/* >> + * Copyright © 2016 Red Hat. >> + * Copyright © 2016 Bas Nieuwenhuizen >> + * >> + * based on amdgpu winsys. >> + * Copyright © 2011 Marek Olšák <mar...@gmail.com> >> + * Copyright © 2015 Advanced Micro Devices, Inc. >> + * >> + * 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, >> sublicense, >> + * 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 above copyright notice and this permission notice (including >> the next >> + * paragraph) shall be included in all copies or substantial portions >> of the >> + * Software. >> + * >> + * 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 NONINFRINGEMENT. IN NO EVENT >> SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS 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. >> + */ >> + >> +#include <stdio.h> >> + >> +#include "radv_amdgpu_bo.h" >> + >> +#include <amdgpu.h> >> +#include <amdgpu_drm.h> >> +#include <inttypes.h> >> + >> +static void radv_amdgpu_winsys_bo_destroy(struct radeon_winsys_bo *_bo) >> +{ >> + struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo); >> + >> + if (bo->ws->debug_all_bos) { >> + pthread_mutex_lock(&bo->ws->global_bo_list_lock); >> + LIST_DEL(&bo->global_list_item); >> + bo->ws->num_buffers--; >> + pthread_mutex_unlock(&bo->ws->global_bo_list_lock); >> + } >> + amdgpu_bo_va_op(bo->bo, 0, bo->size, bo->va, 0, AMDGPU_VA_OP_UNMAP); >> + amdgpu_va_range_free(bo->va_handle); >> + amdgpu_bo_free(bo->bo); >> + FREE(bo); >> +} >> + >> +static void radv_amdgpu_add_buffer_to_global_list(struct >> radv_amdgpu_winsys_bo *bo) >> +{ >> + struct radv_amdgpu_winsys *ws = bo->ws; >> + >> + if (bo->ws->debug_all_bos) { >> + pthread_mutex_lock(&ws->global_bo_list_lock); >> + LIST_ADDTAIL(&bo->global_list_item, &ws->global_bo_list); >> + ws->num_buffers++; >> + pthread_mutex_unlock(&ws->global_bo_list_lock); >> + } >> +} >> + >> +static struct radeon_winsys_bo * >> +radv_amdgpu_winsys_bo_create(struct radeon_winsys *_ws, >> + uint64_t size, >> + unsigned alignment, >> + enum radeon_bo_domain initial_domain, >> + unsigned flags) >> +{ >> + struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws); >> + struct radv_amdgpu_winsys_bo *bo; >> + struct amdgpu_bo_alloc_request request = {0}; >> + amdgpu_bo_handle buf_handle; >> + uint64_t va = 0; >> + amdgpu_va_handle va_handle; >> + int r; >> + bo = CALLOC_STRUCT(radv_amdgpu_winsys_bo); >> + if (!bo) { >> + return NULL; >> + } >> + >> + request.alloc_size = size; >> + request.phys_alignment = alignment; >> + >> + 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_CPU_ACCESS) >> + request.flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; >> + 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; >> + >> + 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; >> + } >> + >> + r = amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general, >> + size, alignment, 0, &va, &va_handle, 0); >> + if (r) >> + goto error_va_alloc; >> + >> + r = amdgpu_bo_va_op(buf_handle, 0, size, va, 0, AMDGPU_VA_OP_MAP); >> + if (r) >> + goto error_va_map; >> + >> + bo->bo = buf_handle; >> + bo->va = va; >> + bo->va_handle = va_handle; >> + bo->initial_domain = initial_domain; >> + bo->size = size; >> + bo->is_shared = false; >> + bo->ws = ws; >> + radv_amdgpu_add_buffer_to_global_list(bo); >> + return (struct radeon_winsys_bo *)bo; >> +error_va_map: >> + amdgpu_va_range_free(va_handle); >> + >> +error_va_alloc: >> + amdgpu_bo_free(buf_handle); >> + >> +error_bo_alloc: >> + FREE(bo); >> + return NULL; >> +} >> + >> +static uint64_t radv_amdgpu_winsys_bo_get_va(struct radeon_winsys_bo >> *_bo) >> +{ >> + struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo); >> + return bo->va; >> +} >> + >> +static void * >> +radv_amdgpu_winsys_bo_map(struct radeon_winsys_bo *_bo) >> +{ >> + struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo); >> + int ret; >> + void *data; >> + ret = amdgpu_bo_cpu_map(bo->bo, &data); >> + if (ret) >> + return NULL; >> + return data; >> +} >> + >> +static void >> +radv_amdgpu_winsys_bo_unmap(struct radeon_winsys_bo *_bo) >> +{ >> + struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo); >> + amdgpu_bo_cpu_unmap(bo->bo); >> +} >> + >> +static struct radeon_winsys_bo * >> +radv_amdgpu_winsys_bo_from_fd(struct radeon_winsys *_ws, >> + int fd, unsigned *stride, >> + unsigned *offset) >> +{ >> + struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws); >> + struct radv_amdgpu_winsys_bo *bo; >> + uint64_t va; >> + amdgpu_va_handle va_handle; >> + enum amdgpu_bo_handle_type type = amdgpu_bo_handle_type_dma_buf_fd; >> + struct amdgpu_bo_import_result result = {0}; >> + struct amdgpu_bo_info info = {0}; >> + enum radeon_bo_domain initial = 0; >> + int r; >> + bo = CALLOC_STRUCT(radv_amdgpu_winsys_bo); >> + if (!bo) >> + return NULL; >> + >> + r = amdgpu_bo_import(ws->dev, type, fd, &result); >> + if (r) >> + goto error; >> + >> + r = amdgpu_bo_query_info(result.buf_handle, &info); >> + if (r) >> + goto error_query; >> + >> + r = amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general, >> + result.alloc_size, 1 << 20, 0, &va, &va_handle, 0); >> + if (r) >> + goto error_query; >> + >> + r = amdgpu_bo_va_op(result.buf_handle, 0, result.alloc_size, va, >> 0, AMDGPU_VA_OP_MAP); >> + if (r) >> + goto error_va_map; >> + >> + if (info.preferred_heap & AMDGPU_GEM_DOMAIN_VRAM) >> + initial |= RADEON_DOMAIN_VRAM; >> + if (info.preferred_heap & AMDGPU_GEM_DOMAIN_GTT) >> + initial |= RADEON_DOMAIN_GTT; >> + >> + bo->bo = result.buf_handle; >> + bo->va = va; >> + bo->va_handle = va_handle; >> + bo->initial_domain = initial; >> + bo->size = result.alloc_size; >> + bo->is_shared = true; >> + return (struct radeon_winsys_bo *)bo; >> +error_va_map: >> + amdgpu_va_range_free(va_handle); >> + >> +error_query: >> + amdgpu_bo_free(result.buf_handle); >> + >> +error: >> + FREE(bo); >> + return NULL; >> +} >> + >> +static bool >> +radv_amdgpu_winsys_get_fd(struct radeon_winsys *_ws, >> + struct radeon_winsys_bo *_bo, >> + int *fd) >> +{ >> + struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo); >> + enum amdgpu_bo_handle_type type = amdgpu_bo_handle_type_dma_buf_fd; >> + int r; >> + unsigned handle; >> + r = amdgpu_bo_export(bo->bo, type, &handle); >> + if (r) >> + return false; >> + >> + *fd = (int)handle; >> + bo->is_shared = true; >> + return true; >> +} >> + >> +static unsigned radv_eg_tile_split_rev(unsigned eg_tile_split) >> +{ >> + switch (eg_tile_split) { >> + case 64: return 0; >> + case 128: return 1; >> + case 256: return 2; >> + case 512: return 3; >> + default: >> + case 1024: return 4; >> + case 2048: return 5; >> + case 4096: return 6; >> + } >> +} >> + >> +static void >> +radv_amdgpu_winsys_bo_set_metadata(struct radeon_winsys_bo *_bo, >> + struct radeon_bo_metadata *md) >> +{ >> + struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo); >> + struct amdgpu_bo_metadata metadata = {0}; >> + uint32_t tiling_flags = 0; >> + >> + if (md->macrotile == RADEON_LAYOUT_TILED) >> + tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 4); /* >> 2D_TILED_THIN1 */ >> + else if (md->microtile == RADEON_LAYOUT_TILED) >> + tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 2); /* >> 1D_TILED_THIN1 */ >> + else >> + tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 1); /* >> LINEAR_ALIGNED */ >> + >> + tiling_flags |= AMDGPU_TILING_SET(PIPE_CONFIG, md->pipe_config); >> + tiling_flags |= AMDGPU_TILING_SET(BANK_WIDTH, >> util_logbase2(md->bankw)); >> + tiling_flags |= AMDGPU_TILING_SET(BANK_HEIGHT, >> util_logbase2(md->bankh)); >> + if (md->tile_split) >> + tiling_flags |= AMDGPU_TILING_SET(TILE_SPLIT, >> radv_eg_tile_split_rev(md->tile_split)); >> + tiling_flags |= AMDGPU_TILING_SET(MACRO_TILE_ASPECT, >> util_logbase2(md->mtilea)); >> + tiling_flags |= AMDGPU_TILING_SET(NUM_BANKS, >> util_logbase2(md->num_banks)-1); >> + >> + if (md->scanout) >> + tiling_flags |= AMDGPU_TILING_SET(MICRO_TILE_MODE, 0); /* >> DISPLAY_MICRO_TILING */ >> + else >> + tiling_flags |= AMDGPU_TILING_SET(MICRO_TILE_MODE, 1); /* >> THIN_MICRO_TILING */ >> + >> + metadata.tiling_info = tiling_flags; >> + metadata.size_metadata = md->size_metadata; >> + memcpy(metadata.umd_metadata, md->metadata, sizeof(md->metadata)); >> + >> + amdgpu_bo_set_metadata(bo->bo, &metadata); >> +} >> + >> +void radv_amdgpu_bo_init_functions(struct radv_amdgpu_winsys *ws) >> +{ >> + ws->base.buffer_create = radv_amdgpu_winsys_bo_create; >> + ws->base.buffer_destroy = radv_amdgpu_winsys_bo_destroy; >> + ws->base.buffer_get_va = radv_amdgpu_winsys_bo_get_va; >> + ws->base.buffer_map = radv_amdgpu_winsys_bo_map; >> + ws->base.buffer_unmap = radv_amdgpu_winsys_bo_unmap; >> + ws->base.buffer_from_fd = radv_amdgpu_winsys_bo_from_fd; >> + ws->base.buffer_get_fd = radv_amdgpu_winsys_get_fd; >> + ws->base.buffer_set_metadata = radv_amdgpu_winsys_bo_set_metadata; >> +} >> diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.h >> b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.h >> new file mode 100644 >> index 0000000..59a1bb7 >> --- /dev/null >> +++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.h >> @@ -0,0 +1,50 @@ >> +/* >> + * Copyright © 2016 Red Hat. >> + * Copyright © 2016 Bas Nieuwenhuizen >> + * >> + * based on amdgpu winsys. >> + * Copyright © 2011 Marek Olšák <mar...@gmail.com> >> + * Copyright © 2015 Advanced Micro Devices, Inc. >> + * >> + * 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, >> sublicense, >> + * 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 above copyright notice and this permission notice (including >> the next >> + * paragraph) shall be included in all copies or substantial portions >> of the >> + * Software. >> + * >> + * 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 NONINFRINGEMENT. IN NO EVENT >> SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS 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. >> + */ >> +#pragma once >> +#include "radv_amdgpu_winsys.h" >> +struct radv_amdgpu_winsys_bo { >> + amdgpu_bo_handle bo; >> + amdgpu_va_handle va_handle; >> + >> + uint64_t va; >> + enum radeon_bo_domain initial_domain; >> + uint64_t size; >> + bool is_shared; >> + >> + struct radv_amdgpu_winsys *ws; >> + struct list_head global_list_item; >> +}; >> + >> +static inline >> +struct radv_amdgpu_winsys_bo *radv_amdgpu_winsys_bo(struct >> radeon_winsys_bo *bo) >> +{ >> + return (struct radv_amdgpu_winsys_bo *)bo; >> +} >> + >> +void radv_amdgpu_bo_init_functions(struct radv_amdgpu_winsys *ws); >> + >> diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.c >> b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.c >> new file mode 100644 >> index 0000000..dedc778 >> --- /dev/null >> +++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.c >> @@ -0,0 +1,778 @@ >> +/* >> + * Copyright © 2016 Red Hat. >> + * Copyright © 2016 Bas Nieuwenhuizen >> + * >> + * 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, >> sublicense, >> + * 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 above copyright notice and this permission notice (including >> the next >> + * paragraph) shall be included in all copies or substantial portions >> of the >> + * Software. >> + * >> + * 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 NONINFRINGEMENT. IN NO EVENT >> SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS 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. >> + */ >> + >> +#include <stdlib.h> >> +#include <amdgpu.h> >> +#include <amdgpu_drm.h> >> +#include <assert.h> >> + >> +#include "amdgpu_id.h" >> +#include "radv_radeon_winsys.h" >> +#include "radv_amdgpu_cs.h" >> +#include "radv_amdgpu_bo.h" >> +#include "sid.h" >> + >> +struct radv_amdgpu_cs { >> + struct radeon_winsys_cs base; >> + struct radv_amdgpu_winsys *ws; >> + >> + struct amdgpu_cs_ib_info ib; >> + >> + struct radeon_winsys_bo *ib_buffer; >> + uint8_t *ib_mapped; >> + unsigned max_num_buffers; >> + unsigned num_buffers; >> + amdgpu_bo_handle *handles; >> + uint8_t *priorities; >> + >> + struct radeon_winsys_bo **old_ib_buffers; >> + unsigned num_old_ib_buffers; >> + unsigned max_num_old_ib_buffers; >> + unsigned *ib_size_ptr; >> + bool failed; >> + bool is_chained; >> + >> + int buffer_hash_table[1024]; >> +}; >> + >> +static inline struct radv_amdgpu_cs * >> +radv_amdgpu_cs(struct radeon_winsys_cs *base) >> +{ >> + return (struct radv_amdgpu_cs*)base; >> +} >> + >> + >> +static struct radeon_winsys_fence *radv_amdgpu_create_fence() >> +{ >> + struct radv_amdgpu_cs_fence *fence = calloc(1, sizeof(struct >> amdgpu_cs_fence)); >> + return (struct radeon_winsys_fence*)fence; >> +} >> + >> +static void radv_amdgpu_destroy_fence(struct radeon_winsys_fence >> *_fence) >> +{ >> + struct amdgpu_cs_fence *fence = (struct amdgpu_cs_fence *)_fence; >> + free(fence); >> +} >> + >> +static bool radv_amdgpu_fence_wait(struct radeon_winsys *_ws, >> + struct radeon_winsys_fence *_fence, >> + bool absolute, >> + uint64_t timeout) >> +{ >> + struct amdgpu_cs_fence *fence = (struct amdgpu_cs_fence *)_fence; >> + unsigned flags = absolute ? >> AMDGPU_QUERY_FENCE_TIMEOUT_IS_ABSOLUTE : 0; >> + int r; >> + uint32_t expired = 0; >> + /* Now use the libdrm query. */ >> + r = amdgpu_cs_query_fence_status(fence, >> + timeout, >> + flags, >> + &expired); >> + >> + if (r) { >> + fprintf(stderr, "amdgpu: radv_amdgpu_cs_query_fence_status >> failed.\n"); >> + return false; >> + } >> + >> + if (expired) { >> + return true; >> + } >> + return false; >> + >> +} >> + >> +static void radv_amdgpu_cs_destroy(struct radeon_winsys_cs *rcs) >> +{ >> + struct radv_amdgpu_cs *cs = radv_amdgpu_cs(rcs); >> + if (cs->ib_buffer) >> + cs->ws->base.buffer_destroy(cs->ib_buffer); >> + else >> + free(cs->base.buf); >> + >> + for (unsigned i = 0; i < cs->num_old_ib_buffers; ++i) >> + cs->ws->base.buffer_destroy(cs->old_ib_buffers[i]); >> + free(cs->old_ib_buffers); >> + free(cs->handles); >> + free(cs->priorities); >> + free(cs); >> +} >> + >> +static boolean radv_amdgpu_init_cs(struct radv_amdgpu_cs *cs, >> + enum ring_type ring_type) >> +{ >> + for (int i = 0; i < ARRAY_SIZE(cs->buffer_hash_table); ++i) { >> + cs->buffer_hash_table[i] = -1; >> + } >> + return true; >> +} >> + >> +static struct radeon_winsys_cs * >> +radv_amdgpu_cs_create(struct radeon_winsys *ws, >> + enum ring_type ring_type) >> +{ >> + struct radv_amdgpu_cs *cs; >> + uint32_t ib_size = 20 * 1024 * 4; >> + cs = calloc(1, sizeof(struct radv_amdgpu_cs)); >> + if (!cs) >> + return NULL; >> + >> + cs->ws = radv_amdgpu_winsys(ws); >> + radv_amdgpu_init_cs(cs, RING_GFX); >> + >> + if (cs->ws->use_ib_bos) { >> + cs->ib_buffer = ws->buffer_create(ws, ib_size, 0, >> + RADEON_DOMAIN_GTT, >> + RADEON_FLAG_CPU_ACCESS); >> + if (!cs->ib_buffer) { >> + free(cs); >> + return NULL; >> + } >> + >> + cs->ib_mapped = ws->buffer_map(cs->ib_buffer); >> + if (!cs->ib_mapped) { >> + ws->buffer_destroy(cs->ib_buffer); >> + free(cs); >> + return NULL; >> + } >> + >> + cs->ib.ib_mc_address = radv_amdgpu_winsys_bo(cs->ib_buffer)->va; >> + cs->base.buf = (uint32_t *)cs->ib_mapped; >> + cs->base.max_dw = ib_size / 4 - 4; >> + cs->ib_size_ptr = &cs->ib.size; >> + cs->ib.size = 0; >> + >> + ws->cs_add_buffer(&cs->base, cs->ib_buffer, 8); >> + } else { >> + cs->base.buf = malloc(16384); >> + cs->base.max_dw = 4096; >> + if (!cs->base.buf) { >> + free(cs); >> + return NULL; >> + } >> + } >> + >> + return &cs->base; >> +} >> + >> +static void radv_amdgpu_cs_grow(struct radeon_winsys_cs *_cs, size_t >> min_size) >> +{ >> + struct radv_amdgpu_cs *cs = radv_amdgpu_cs(_cs); >> + uint64_t ib_size = MAX2(min_size * 4 + 16, cs->base.max_dw * 4 * 2); >> + >> + /* max that fits in the chain size field. */ >> + ib_size = MIN2(ib_size, 0xfffff); >> + >> + if (cs->failed) { >> + cs->base.cdw = 0; >> + return; >> + } >> + >> + if (!cs->ws->use_ib_bos) { >> + uint32_t *new_buf = realloc(cs->base.buf, ib_size); >> + if (new_buf) { >> + cs->base.buf = new_buf; >> + cs->base.max_dw = ib_size / 4; >> + } else { >> + cs->failed = true; >> + cs->base.cdw = 0; >> + } >> + return; >> + } >> + >> + while (!cs->base.cdw || (cs->base.cdw & 7) != 4) >> + cs->base.buf[cs->base.cdw++] = 0xffff1000; >> + >> + *cs->ib_size_ptr |= cs->base.cdw + 4; >> + >> + if (cs->num_old_ib_buffers == cs->max_num_old_ib_buffers) { >> + cs->max_num_old_ib_buffers = MAX2(1, >> cs->max_num_old_ib_buffers * 2); >> + cs->old_ib_buffers = realloc(cs->old_ib_buffers, >> + cs->max_num_old_ib_buffers * sizeof(void*)); >> + } >> + >> + cs->old_ib_buffers[cs->num_old_ib_buffers++] = cs->ib_buffer; >> + >> + cs->ib_buffer = cs->ws->base.buffer_create(&cs->ws->base, >> ib_size, 0, >> + RADEON_DOMAIN_GTT, >> + RADEON_FLAG_CPU_ACCESS); >> + >> + if (!cs->ib_buffer) { >> + cs->base.cdw = 0; >> + cs->failed = true; >> + cs->ib_buffer = cs->old_ib_buffers[--cs->num_old_ib_buffers]; >> + } >> + >> + cs->ib_mapped = cs->ws->base.buffer_map(cs->ib_buffer); >> + if (!cs->ib_mapped) { >> + cs->ws->base.buffer_destroy(cs->ib_buffer); >> + cs->base.cdw = 0; >> + cs->failed = true; >> + cs->ib_buffer = cs->old_ib_buffers[--cs->num_old_ib_buffers]; >> + } >> + >> + cs->ws->base.cs_add_buffer(&cs->base, cs->ib_buffer, 8); >> + >> + cs->base.buf[cs->base.cdw++] = PKT3(PKT3_INDIRECT_BUFFER_CIK, 2, 0); >> + cs->base.buf[cs->base.cdw++] = >> radv_amdgpu_winsys_bo(cs->ib_buffer)->va; >> + cs->base.buf[cs->base.cdw++] = >> radv_amdgpu_winsys_bo(cs->ib_buffer)->va >> 32; >> + cs->ib_size_ptr = cs->base.buf + cs->base.cdw; >> + cs->base.buf[cs->base.cdw++] = S_3F2_CHAIN(1) | S_3F2_VALID(1); >> + >> + cs->base.buf = (uint32_t *)cs->ib_mapped; >> + cs->base.cdw = 0; >> + cs->base.max_dw = ib_size / 4 - 4; >> + >> +} >> + >> +static bool radv_amdgpu_cs_finalize(struct radeon_winsys_cs *_cs) >> +{ >> + struct radv_amdgpu_cs *cs = radv_amdgpu_cs(_cs); >> + >> + if (cs->ws->use_ib_bos) { >> + while (!cs->base.cdw || (cs->base.cdw & 7) != 0) >> + cs->base.buf[cs->base.cdw++] = 0xffff1000; >> + >> + *cs->ib_size_ptr |= cs->base.cdw; >> + >> + cs->is_chained = false; >> + } >> + >> + return !cs->failed; >> +} >> + >> +static void radv_amdgpu_cs_reset(struct radeon_winsys_cs *_cs) >> +{ >> + struct radv_amdgpu_cs *cs = radv_amdgpu_cs(_cs); >> + cs->base.cdw = 0; >> + cs->failed = false; >> + >> + for (unsigned i = 0; i < cs->num_buffers; ++i) { >> + unsigned hash = ((uintptr_t)cs->handles[i] >> 6) & >> + (ARRAY_SIZE(cs->buffer_hash_table) - 1); >> + cs->buffer_hash_table[hash] = -1; >> + } >> + >> + cs->num_buffers = 0; >> + >> + if (cs->ws->use_ib_bos) { >> + cs->ws->base.cs_add_buffer(&cs->base, cs->ib_buffer, 8); >> + >> + for (unsigned i = 0; i < cs->num_old_ib_buffers; ++i) >> + cs->ws->base.buffer_destroy(cs->old_ib_buffers[i]); >> + >> + cs->num_old_ib_buffers = 0; >> + cs->ib.ib_mc_address = radv_amdgpu_winsys_bo(cs->ib_buffer)->va; >> + cs->ib_size_ptr = &cs->ib.size; >> + cs->ib.size = 0; >> + } >> +} >> + >> +static int radv_amdgpu_cs_find_buffer(struct radv_amdgpu_cs *cs, >> + amdgpu_bo_handle bo) >> +{ >> + unsigned hash = ((uintptr_t)bo >> 6) & >> (ARRAY_SIZE(cs->buffer_hash_table) - 1); >> + int index = cs->buffer_hash_table[hash]; >> + >> + if (index == -1) >> + return -1; >> + >> + if(cs->handles[index] == bo) >> + return index; >> + >> + for (unsigned i = 0; i < cs->num_buffers; ++i) { >> + if (cs->handles[i] == bo) { >> + cs->buffer_hash_table[hash] = i; >> + return i; >> + } >> + } >> + return -1; >> +} >> + >> +static void radv_amdgpu_cs_add_buffer_internal(struct radv_amdgpu_cs >> *cs, >> + amdgpu_bo_handle bo, >> + uint8_t priority) >> +{ >> + unsigned hash; >> + int index = radv_amdgpu_cs_find_buffer(cs, bo); >> + >> + if (index != -1) { >> + cs->priorities[index] = MAX2(cs->priorities[index], priority); >> + return; >> + } >> + >> + if (cs->num_buffers == cs->max_num_buffers) { >> + unsigned new_count = MAX2(1, cs->max_num_buffers * 2); >> + cs->handles = realloc(cs->handles, new_count * >> sizeof(amdgpu_bo_handle)); >> + cs->priorities = realloc(cs->priorities, new_count * >> sizeof(uint8_t)); >> + cs->max_num_buffers = new_count; >> + } >> + >> + cs->handles[cs->num_buffers] = bo; >> + cs->priorities[cs->num_buffers] = priority; >> + >> + hash = ((uintptr_t)bo >> 6) & (ARRAY_SIZE(cs->buffer_hash_table) >> - 1); >> + cs->buffer_hash_table[hash] = cs->num_buffers; >> + >> + ++cs->num_buffers; >> +} >> + >> +static void radv_amdgpu_cs_add_buffer(struct radeon_winsys_cs *_cs, >> + struct radeon_winsys_bo *_bo, >> + uint8_t priority) >> +{ >> + struct radv_amdgpu_cs *cs = radv_amdgpu_cs(_cs); >> + struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo); >> + >> + radv_amdgpu_cs_add_buffer_internal(cs, bo->bo, priority); >> +} >> + >> +static void radv_amdgpu_cs_execute_secondary(struct radeon_winsys_cs >> *_parent, >> + struct radeon_winsys_cs *_child) >> +{ >> + struct radv_amdgpu_cs *parent = radv_amdgpu_cs(_parent); >> + struct radv_amdgpu_cs *child = radv_amdgpu_cs(_child); >> + >> + for (unsigned i = 0; i < child->num_buffers; ++i) { >> + radv_amdgpu_cs_add_buffer_internal(parent, child->handles[i], >> + child->priorities[i]); >> + } >> + >> + if (parent->ws->use_ib_bos) { >> + if (parent->base.cdw + 4 > parent->base.max_dw) >> + radv_amdgpu_cs_grow(&parent->base, 4); >> + >> + parent->base.buf[parent->base.cdw++] = >> PKT3(PKT3_INDIRECT_BUFFER_CIK, 2, 0); >> + parent->base.buf[parent->base.cdw++] = child->ib.ib_mc_address; >> + parent->base.buf[parent->base.cdw++] = >> child->ib.ib_mc_address >> 32; >> + parent->base.buf[parent->base.cdw++] = child->ib.size; >> + } else { >> + if (parent->base.cdw + child->base.cdw > parent->base.max_dw) >> + radv_amdgpu_cs_grow(&parent->base, child->base.cdw); >> + >> + memcpy(parent->base.buf + parent->base.cdw, child->base.buf, >> 4 * child->base.cdw); >> + parent->base.cdw += child->base.cdw; >> + } >> +} >> + >> +static int radv_amdgpu_create_bo_list(struct radv_amdgpu_winsys *ws, >> + struct radeon_winsys_cs **cs_array, >> + unsigned count, >> + struct radv_amdgpu_winsys_bo *extra_bo, >> + amdgpu_bo_list_handle *bo_list) >> +{ >> + int r; >> + if (ws->debug_all_bos) { >> + struct radv_amdgpu_winsys_bo *bo; >> + amdgpu_bo_handle *handles; >> + unsigned num = 0; >> + >> + pthread_mutex_lock(&ws->global_bo_list_lock); >> + >> + handles = malloc(sizeof(handles[0]) * ws->num_buffers); >> + if (!handles) { >> + pthread_mutex_unlock(&ws->global_bo_list_lock); >> + return -ENOMEM; >> + } >> + >> + LIST_FOR_EACH_ENTRY(bo, &ws->global_bo_list, global_list_item) { >> + assert(num < ws->num_buffers); >> + handles[num++] = bo->bo; >> + } >> + >> + r = amdgpu_bo_list_create(ws->dev, ws->num_buffers, >> + handles, NULL, >> + bo_list); >> + free(handles); >> + pthread_mutex_unlock(&ws->global_bo_list_lock); >> + } else if (count == 1 && !extra_bo) { >> + struct radv_amdgpu_cs *cs = (struct radv_amdgpu_cs*)cs_array[0]; >> + r = amdgpu_bo_list_create(ws->dev, cs->num_buffers, cs->handles, >> + cs->priorities, bo_list); >> + } else { >> + unsigned total_buffer_count = !!extra_bo; >> + unsigned unique_bo_count = !!extra_bo; >> + for (unsigned i = 0; i < count; ++i) { >> + struct radv_amdgpu_cs *cs = (struct >> radv_amdgpu_cs*)cs_array[i]; >> + total_buffer_count += cs->num_buffers; >> + } >> + >> + amdgpu_bo_handle *handles = malloc(sizeof(amdgpu_bo_handle) * >> total_buffer_count); >> + uint8_t *priorities = malloc(sizeof(uint8_t) * >> total_buffer_count); >> + if (!handles || !priorities) { >> + free(handles); >> + free(priorities); >> + return -ENOMEM; >> + } >> + >> + if (extra_bo) { >> + handles[0] = extra_bo->bo; >> + priorities[0] = 8; >> + } >> + >> + for (unsigned i = 0; i < count; ++i) { >> + struct radv_amdgpu_cs *cs = (struct >> radv_amdgpu_cs*)cs_array[i]; >> + for (unsigned j = 0; j < cs->num_buffers; ++j) { >> + bool found = false; >> + for (unsigned k = 0; k < unique_bo_count; ++k) { >> + if (handles[k] == cs->handles[j]) { >> + found = true; >> + priorities[k] = MAX2(priorities[k], >> + cs->priorities[j]); >> + break; >> + } >> + } >> + if (!found) { >> + handles[unique_bo_count] = cs->handles[j]; >> + priorities[unique_bo_count] = cs->priorities[j]; >> + ++unique_bo_count; >> + } >> + } >> + } >> + r = amdgpu_bo_list_create(ws->dev, unique_bo_count, handles, >> + priorities, bo_list); >> + >> + free(handles); >> + free(priorities); >> + } >> + return r; >> +} >> + >> +static int radv_amdgpu_winsys_cs_submit_chained(struct >> radeon_winsys_ctx *_ctx, >> + struct radeon_winsys_cs **cs_array, >> + unsigned cs_count, >> + struct radeon_winsys_fence *_fence) >> +{ >> + int r; >> + struct radv_amdgpu_ctx *ctx = radv_amdgpu_ctx(_ctx); >> + struct amdgpu_cs_fence *fence = (struct amdgpu_cs_fence *)_fence; >> + struct radv_amdgpu_cs *cs0 = radv_amdgpu_cs(cs_array[0]); >> + amdgpu_bo_list_handle bo_list; >> + struct amdgpu_cs_request request = {0}; >> + >> + for (unsigned i = cs_count; i--;) { >> + struct radv_amdgpu_cs *cs = radv_amdgpu_cs(cs_array[i]); >> + >> + if (cs->is_chained) { >> + *cs->ib_size_ptr -= 4; >> + cs->is_chained = false; >> + } >> + >> + if (i + 1 < cs_count) { >> + struct radv_amdgpu_cs *next = radv_amdgpu_cs(cs_array[i + >> 1]); >> + assert(cs->base.cdw + 4 <= cs->base.max_dw); >> + >> + cs->is_chained = true; >> + *cs->ib_size_ptr += 4; >> + >> + cs->base.buf[cs->base.cdw + 0] = >> PKT3(PKT3_INDIRECT_BUFFER_CIK, 2, 0); >> + cs->base.buf[cs->base.cdw + 1] = next->ib.ib_mc_address; >> + cs->base.buf[cs->base.cdw + 2] = next->ib.ib_mc_address >> >> 32; >> + cs->base.buf[cs->base.cdw + 3] = S_3F2_CHAIN(1) | >> S_3F2_VALID(1) | next->ib.size; >> + } >> + } >> + >> + r = radv_amdgpu_create_bo_list(cs0->ws, cs_array, cs_count, NULL, >> &bo_list); >> + if (r) { >> + fprintf(stderr, "amdgpu: Failed to created the BO list for >> submission\n"); >> + return r; >> + } >> + >> + request.ip_type = AMDGPU_HW_IP_GFX; >> + request.number_of_ibs = 1; >> + request.ibs = &cs0->ib; >> + request.resources = bo_list; >> + >> + r = amdgpu_cs_submit(ctx->ctx, 0, &request, 1); >> + if (r) { >> + if (r == -ENOMEM) >> + fprintf(stderr, "amdgpu: Not enough memory for command >> submission.\n"); >> + else >> + fprintf(stderr, "amdgpu: The CS has been rejected, " >> + "see dmesg for more information.\n"); >> + } >> + >> + amdgpu_bo_list_destroy(bo_list); >> + >> + if (fence) { >> + fence->context = ctx->ctx; >> + fence->ip_type = request.ip_type; >> + fence->ip_instance = request.ip_instance; >> + fence->ring = request.ring; >> + fence->fence = request.seq_no; >> + } >> + ctx->last_seq_no = request.seq_no; >> + >> + return r; >> +} >> + >> +static int radv_amdgpu_winsys_cs_submit_fallback(struct >> radeon_winsys_ctx *_ctx, >> + struct radeon_winsys_cs **cs_array, >> + unsigned cs_count, >> + struct radeon_winsys_fence *_fence) >> +{ >> + int r; >> + struct radv_amdgpu_ctx *ctx = radv_amdgpu_ctx(_ctx); >> + struct amdgpu_cs_fence *fence = (struct amdgpu_cs_fence *)_fence; >> + amdgpu_bo_list_handle bo_list; >> + struct amdgpu_cs_request request; >> + >> + assert(cs_count); >> + >> + for (unsigned i = 0; i < cs_count;) { >> + struct radv_amdgpu_cs *cs0 = radv_amdgpu_cs(cs_array[i]); >> + struct amdgpu_cs_ib_info ibs[AMDGPU_CS_MAX_IBS_PER_SUBMIT]; >> + unsigned cnt = MIN2(AMDGPU_CS_MAX_IBS_PER_SUBMIT, cs_count - i); >> + >> + memset(&request, 0, sizeof(request)); >> + >> + r = radv_amdgpu_create_bo_list(cs0->ws, &cs_array[i], cnt, >> NULL, &bo_list); >> + if (r) { >> + fprintf(stderr, "amdgpu: Failed to created the BO list >> for submission\n"); >> + return r; >> + } >> + >> + request.ip_type = AMDGPU_HW_IP_GFX; >> + request.resources = bo_list; >> + request.number_of_ibs = cnt; >> + request.ibs = ibs; >> + >> + for (unsigned j = 0; j < cnt; ++j) { >> + struct radv_amdgpu_cs *cs = radv_amdgpu_cs(cs_array[i + j]); >> + ibs[j] = cs->ib; >> + >> + if (cs->is_chained) { >> + *cs->ib_size_ptr -= 4; >> + cs->is_chained = false; >> + } >> + } >> + >> + r = amdgpu_cs_submit(ctx->ctx, 0, &request, 1); >> + if (r) { >> + if (r == -ENOMEM) >> + fprintf(stderr, "amdgpu: Not enough memory for >> command submission.\n"); >> + else >> + fprintf(stderr, "amdgpu: The CS has been rejected, " >> + "see dmesg for more information.\n"); >> + } >> + >> + amdgpu_bo_list_destroy(bo_list); >> + >> + if (r) >> + return r; >> + >> + i += cnt; >> + } >> + if (fence) { >> + fence->context = ctx->ctx; >> + fence->ip_type = request.ip_type; >> + fence->ip_instance = request.ip_instance; >> + fence->ring = request.ring; >> + fence->fence = request.seq_no; >> + } >> + ctx->last_seq_no = request.seq_no; >> + >> + return 0; >> +} >> + >> +static int radv_amdgpu_winsys_cs_submit_sysmem(struct >> radeon_winsys_ctx *_ctx, >> + struct radeon_winsys_cs **cs_array, >> + unsigned cs_count, >> + struct radeon_winsys_fence *_fence) >> +{ >> + int r; >> + struct radv_amdgpu_ctx *ctx = radv_amdgpu_ctx(_ctx); >> + struct amdgpu_cs_fence *fence = (struct amdgpu_cs_fence *)_fence; >> + struct radv_amdgpu_cs *cs0 = radv_amdgpu_cs(cs_array[0]); >> + struct radeon_winsys *ws = (struct radeon_winsys*)cs0->ws; >> + amdgpu_bo_list_handle bo_list; >> + struct amdgpu_cs_request request; >> + uint32_t pad_word = 0xffff1000U; >> + >> + if (radv_amdgpu_winsys(ws)->family == FAMILY_SI) >> + pad_word = 0x80000000; >> + >> + assert(cs_count); >> + >> + for (unsigned i = 0; i < cs_count;) { >> + struct amdgpu_cs_ib_info ib = {0}; >> + struct radeon_winsys_bo *bo = NULL; >> + uint32_t *ptr; >> + unsigned cnt = 0; >> + unsigned size = 0; >> + >> + while (i + cnt < cs_count && 0xffff8 - size >= >> radv_amdgpu_cs(cs_array[i + cnt])->base.cdw) { >> + size += radv_amdgpu_cs(cs_array[i + cnt])->base.cdw; >> + ++cnt; >> + } >> + >> + assert(cnt); >> + >> + bo = ws->buffer_create(ws, 4 * size, 4096, RADEON_DOMAIN_GTT, >> RADEON_FLAG_CPU_ACCESS); >> + ptr = ws->buffer_map(bo); >> + >> + for (unsigned j = 0; j < cnt; ++j) { >> + struct radv_amdgpu_cs *cs = radv_amdgpu_cs(cs_array[i + j]); >> + memcpy(ptr, cs->base.buf, 4 * cs->base.cdw); >> + ptr += cs->base.cdw; >> + >> + } >> + >> + while(!size || (size & 7)) { >> + *ptr++ = pad_word; >> + ++size; >> + } >> + >> + memset(&request, 0, sizeof(request)); >> + >> + >> + r = radv_amdgpu_create_bo_list(cs0->ws, &cs_array[i], cnt, >> + (struct >> radv_amdgpu_winsys_bo*)bo, &bo_list); >> + if (r) { >> + fprintf(stderr, "amdgpu: Failed to created the BO list >> for submission\n"); >> + return r; >> + } >> + >> + ib.size = size; >> + ib.ib_mc_address = ws->buffer_get_va(bo); >> + >> + request.ip_type = AMDGPU_HW_IP_GFX; >> + request.resources = bo_list; >> + request.number_of_ibs = 1; >> + request.ibs = &ib; >> + >> + r = amdgpu_cs_submit(ctx->ctx, 0, &request, 1); >> + if (r) { >> + if (r == -ENOMEM) >> + fprintf(stderr, "amdgpu: Not enough memory for >> command submission.\n"); >> + else >> + fprintf(stderr, "amdgpu: The CS has been rejected, " >> + "see dmesg for more information.\n"); >> + } >> + >> + amdgpu_bo_list_destroy(bo_list); >> + >> + ws->buffer_destroy(bo); >> + if (r) >> + return r; >> + >> + i += cnt; >> + } >> + if (fence) { >> + fence->context = ctx->ctx; >> + fence->ip_type = request.ip_type; >> + fence->ip_instance = request.ip_instance; >> + fence->ring = request.ring; >> + fence->fence = request.seq_no; >> + } >> + ctx->last_seq_no = request.seq_no; >> + >> + return 0; >> +} >> + >> +static int radv_amdgpu_winsys_cs_submit(struct radeon_winsys_ctx *_ctx, >> + struct radeon_winsys_cs **cs_array, >> + unsigned cs_count, >> + bool can_patch, >> + struct radeon_winsys_fence *_fence) >> +{ >> + struct radv_amdgpu_cs *cs = radv_amdgpu_cs(cs_array[0]); >> + if (!cs->ws->use_ib_bos) { >> + return radv_amdgpu_winsys_cs_submit_sysmem(_ctx, cs_array, >> + cs_count, _fence); >> + } else if (can_patch && cs_count > AMDGPU_CS_MAX_IBS_PER_SUBMIT >> && false) { >> + return radv_amdgpu_winsys_cs_submit_chained(_ctx, cs_array, >> + cs_count, _fence); >> + } else { >> + return radv_amdgpu_winsys_cs_submit_fallback(_ctx, cs_array, >> + cs_count, _fence); >> + } >> +} >> + >> +static struct radeon_winsys_ctx *radv_amdgpu_ctx_create(struct >> radeon_winsys *_ws) >> +{ >> + struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws); >> + struct radv_amdgpu_ctx *ctx = CALLOC_STRUCT(radv_amdgpu_ctx); >> + int r; >> + >> + if (!ctx) >> + return NULL; >> + r = amdgpu_cs_ctx_create(ws->dev, &ctx->ctx); >> + if (r) { >> + fprintf(stderr, "amdgpu: radv_amdgpu_cs_ctx_create failed. >> (%i)\n", r); >> + goto error_create; >> + } >> + ctx->ws = ws; >> + return (struct radeon_winsys_ctx *)ctx; >> +error_create: >> + return NULL; >> +} >> + >> +static void radv_amdgpu_ctx_destroy(struct radeon_winsys_ctx *rwctx) >> +{ >> + struct radv_amdgpu_ctx *ctx = (struct radv_amdgpu_ctx *)rwctx; >> + amdgpu_cs_ctx_free(ctx->ctx); >> + FREE(ctx); >> +} >> + >> +static bool radv_amdgpu_ctx_wait_idle(struct radeon_winsys_ctx *rwctx) >> +{ >> + struct radv_amdgpu_ctx *ctx = (struct radv_amdgpu_ctx *)rwctx; >> + >> + if (ctx->last_seq_no) { >> + uint32_t expired; >> + struct amdgpu_cs_fence fence; >> + >> + fence.context = ctx->ctx; >> + fence.ip_type = RING_GFX; >> + fence.ip_instance = 0; >> + fence.ring = 0; >> + fence.fence = ctx->last_seq_no; >> + >> + int ret = amdgpu_cs_query_fence_status(&fence, 1000000000ull, 0, >> + &expired); >> + >> + if (ret || !expired) >> + return false; >> + } >> + >> + return true; >> +} >> + >> +void radv_amdgpu_cs_init_functions(struct radv_amdgpu_winsys *ws) >> +{ >> + ws->base.ctx_create = radv_amdgpu_ctx_create; >> + ws->base.ctx_destroy = radv_amdgpu_ctx_destroy; >> + ws->base.ctx_wait_idle = radv_amdgpu_ctx_wait_idle; >> + ws->base.cs_create = radv_amdgpu_cs_create; >> + ws->base.cs_destroy = radv_amdgpu_cs_destroy; >> + ws->base.cs_grow = radv_amdgpu_cs_grow; >> + ws->base.cs_finalize = radv_amdgpu_cs_finalize; >> + ws->base.cs_reset = radv_amdgpu_cs_reset; >> + ws->base.cs_add_buffer = radv_amdgpu_cs_add_buffer; >> + ws->base.cs_execute_secondary = radv_amdgpu_cs_execute_secondary; >> + ws->base.cs_submit = radv_amdgpu_winsys_cs_submit; >> + ws->base.create_fence = radv_amdgpu_create_fence; >> + ws->base.destroy_fence = radv_amdgpu_destroy_fence; >> + ws->base.fence_wait = radv_amdgpu_fence_wait; >> +} >> diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.h >> b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.h >> new file mode 100644 >> index 0000000..d36a3b8 >> --- /dev/null >> +++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.h >> @@ -0,0 +1,52 @@ >> +/* >> + * Copyright © 2016 Red Hat. >> + * Copyright © 2016 Bas Nieuwenhuizen >> + * >> + * based on amdgpu winsys. >> + * Copyright © 2011 Marek Olšák <mar...@gmail.com> >> + * Copyright © 2015 Advanced Micro Devices, Inc. >> + * >> + * 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, >> sublicense, >> + * 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 above copyright notice and this permission notice (including >> the next >> + * paragraph) shall be included in all copies or substantial portions >> of the >> + * Software. >> + * >> + * 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 NONINFRINGEMENT. IN NO EVENT >> SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS 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. >> + */ >> +#pragma once >> + >> +#include <string.h> >> +#include <stdint.h> >> +#include <assert.h> >> +#include "r600d_common.h" >> +#include <amdgpu.h> >> + >> +#include "radv_radeon_winsys.h" >> + >> +#include "radv_amdgpu_winsys.h" >> +struct radv_amdgpu_ctx { >> + struct radv_amdgpu_winsys *ws; >> + amdgpu_context_handle ctx; >> + uint64_t last_seq_no; >> +}; >> + >> +static inline struct radv_amdgpu_ctx * >> +radv_amdgpu_ctx(struct radeon_winsys_ctx *base) >> +{ >> + return (struct radv_amdgpu_ctx *)base; >> +} >> + >> + >> +void radv_amdgpu_cs_init_functions(struct radv_amdgpu_winsys *ws); >> diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_surface.c >> b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_surface.c >> new file mode 100644 >> index 0000000..a3c2411 >> --- /dev/null >> +++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_surface.c >> @@ -0,0 +1,523 @@ >> +/* >> + * Copyright © 2016 Red Hat. >> + * Copyright © 2016 Bas Nieuwenhuizen >> + * >> + * based on amdgpu winsys. >> + * Copyright © 2011 Marek Olšák <mar...@gmail.com> >> + * Copyright © 2015 Advanced Micro Devices, Inc. >> + * >> + * 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, >> sublicense, >> + * 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 above copyright notice and this permission notice (including >> the next >> + * paragraph) shall be included in all copies or substantial portions >> of the >> + * Software. >> + * >> + * 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 NONINFRINGEMENT. IN NO EVENT >> SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS 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. >> + */ >> + >> +#include <errno.h> >> +#include "radv_private.h" >> +#include "addrlib/addrinterface.h" >> +#include "util/bitset.h" >> +#include "radv_amdgpu_winsys.h" >> +#include "radv_amdgpu_surface.h" >> +#include "sid.h" >> +#ifndef NO_ENTRIES >> +#define NO_ENTRIES 32 >> +#endif >> + >> +#ifndef NO_MACRO_ENTRIES >> +#define NO_MACRO_ENTRIES 16 >> +#endif >> + >> +#ifndef CIASICIDGFXENGINE_SOUTHERNISLAND >> +#define CIASICIDGFXENGINE_SOUTHERNISLAND 0x0000000A >> +#endif >> + >> +static int radv_amdgpu_surface_sanity(const struct radeon_surf *surf) >> +{ >> + unsigned type = RADEON_SURF_GET(surf->flags, TYPE); >> + >> + if (!(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) >> + return -EINVAL; >> + >> + /* all dimension must be at least 1 ! */ >> + if (!surf->npix_x || !surf->npix_y || !surf->npix_z || >> + !surf->array_size) >> + return -EINVAL; >> + >> + if (!surf->blk_w || !surf->blk_h || !surf->blk_d) >> + return -EINVAL; >> + >> + switch (surf->nsamples) { >> + case 1: >> + case 2: >> + case 4: >> + case 8: >> + break; >> + default: >> + return -EINVAL; >> + } >> + >> + switch (type) { >> + case RADEON_SURF_TYPE_1D: >> + if (surf->npix_y > 1) >> + return -EINVAL; >> + /* fall through */ >> + case RADEON_SURF_TYPE_2D: >> + case RADEON_SURF_TYPE_CUBEMAP: >> + if (surf->npix_z > 1 || surf->array_size > 1) >> + return -EINVAL; >> + break; >> + case RADEON_SURF_TYPE_3D: >> + if (surf->array_size > 1) >> + return -EINVAL; >> + break; >> + case RADEON_SURF_TYPE_1D_ARRAY: >> + if (surf->npix_y > 1) >> + return -EINVAL; >> + /* fall through */ >> + case RADEON_SURF_TYPE_2D_ARRAY: >> + if (surf->npix_z > 1) >> + return -EINVAL; >> + break; >> + default: >> + return -EINVAL; >> + } >> + return 0; >> +} >> + >> +static void *ADDR_API radv_allocSysMem(const ADDR_ALLOCSYSMEM_INPUT * >> pInput) >> +{ >> + return malloc(pInput->sizeInBytes); >> +} >> + >> +static ADDR_E_RETURNCODE ADDR_API radv_freeSysMem(const >> ADDR_FREESYSMEM_INPUT * pInput) >> +{ >> + free(pInput->pVirtAddr); >> + return ADDR_OK; >> +} >> + >> +ADDR_HANDLE radv_amdgpu_addr_create(struct amdgpu_gpu_info *amdinfo, >> int family, int rev_id, >> + enum chip_class chip_class) >> +{ >> + ADDR_CREATE_INPUT addrCreateInput = {0}; >> + ADDR_CREATE_OUTPUT addrCreateOutput = {0}; >> + ADDR_REGISTER_VALUE regValue = {0}; >> + ADDR_CREATE_FLAGS createFlags = {{0}}; >> + ADDR_E_RETURNCODE addrRet; >> + >> + addrCreateInput.size = sizeof(ADDR_CREATE_INPUT); >> + addrCreateOutput.size = sizeof(ADDR_CREATE_OUTPUT); >> + >> + regValue.noOfBanks = amdinfo->mc_arb_ramcfg & 0x3; >> + regValue.gbAddrConfig = amdinfo->gb_addr_cfg; >> + regValue.noOfRanks = (amdinfo->mc_arb_ramcfg & 0x4) >> 2; >> + >> + regValue.backendDisables = amdinfo->backend_disable[0]; >> + regValue.pTileConfig = amdinfo->gb_tile_mode; >> + regValue.noOfEntries = ARRAY_SIZE(amdinfo->gb_tile_mode); >> + if (chip_class == SI) { >> + regValue.pMacroTileConfig = NULL; >> + regValue.noOfMacroEntries = 0; >> + } else { >> + regValue.pMacroTileConfig = amdinfo->gb_macro_tile_mode; >> + regValue.noOfMacroEntries = >> ARRAY_SIZE(amdinfo->gb_macro_tile_mode); >> + } >> + >> + createFlags.value = 0; >> + createFlags.useTileIndex = 1; >> + createFlags.degradeBaseLevel = 1; >> + >> + addrCreateInput.chipEngine = CIASICIDGFXENGINE_SOUTHERNISLAND; >> + addrCreateInput.chipFamily = family; >> + addrCreateInput.chipRevision = rev_id; >> + addrCreateInput.createFlags = createFlags; >> + addrCreateInput.callbacks.allocSysMem = radv_allocSysMem; >> + addrCreateInput.callbacks.freeSysMem = radv_freeSysMem; >> + addrCreateInput.callbacks.debugPrint = 0; >> + addrCreateInput.regValue = regValue; >> + >> + addrRet = AddrCreate(&addrCreateInput, &addrCreateOutput); >> + if (addrRet != ADDR_OK) >> + return NULL; >> + >> + return addrCreateOutput.hLib; >> +} >> + >> +static int radv_compute_level(ADDR_HANDLE addrlib, >> + struct radeon_surf *surf, bool is_stencil, >> + unsigned level, unsigned type, bool >> compressed, >> + ADDR_COMPUTE_SURFACE_INFO_INPUT >> *AddrSurfInfoIn, >> + ADDR_COMPUTE_SURFACE_INFO_OUTPUT >> *AddrSurfInfoOut, >> + ADDR_COMPUTE_DCCINFO_INPUT *AddrDccIn, >> + ADDR_COMPUTE_DCCINFO_OUTPUT *AddrDccOut) >> +{ >> + struct radeon_surf_level *surf_level; >> + ADDR_E_RETURNCODE ret; >> + >> + AddrSurfInfoIn->mipLevel = level; >> + AddrSurfInfoIn->width = u_minify(surf->npix_x, level); >> + AddrSurfInfoIn->height = u_minify(surf->npix_y, level); >> + >> + if (type == RADEON_SURF_TYPE_3D) >> + AddrSurfInfoIn->numSlices = u_minify(surf->npix_z, level); >> + else if (type == RADEON_SURF_TYPE_CUBEMAP) >> + AddrSurfInfoIn->numSlices = 6; >> + else >> + AddrSurfInfoIn->numSlices = surf->array_size; >> + >> + if (level > 0) { >> + /* Set the base level pitch. This is needed for calculation >> + * of non-zero levels. */ >> + if (is_stencil) >> + AddrSurfInfoIn->basePitch = surf->stencil_level[0].nblk_x; >> + else >> + AddrSurfInfoIn->basePitch = surf->level[0].nblk_x; >> + >> + /* Convert blocks to pixels for compressed formats. */ >> + if (compressed) >> + AddrSurfInfoIn->basePitch *= surf->blk_w; >> + } >> + >> + ret = AddrComputeSurfaceInfo(addrlib, >> + AddrSurfInfoIn, >> + AddrSurfInfoOut); >> + if (ret != ADDR_OK) { >> + return ret; >> + } >> + >> + surf_level = is_stencil ? &surf->stencil_level[level] : >> &surf->level[level]; >> + surf_level->offset = align64(surf->bo_size, >> AddrSurfInfoOut->baseAlign); >> + surf_level->slice_size = AddrSurfInfoOut->sliceSize; >> + surf_level->pitch_bytes = AddrSurfInfoOut->pitch * (is_stencil ? >> 1 : surf->bpe); >> + surf_level->npix_x = u_minify(surf->npix_x, level); >> + surf_level->npix_y = u_minify(surf->npix_y, level); >> + surf_level->npix_z = u_minify(surf->npix_z, level); >> + surf_level->nblk_x = AddrSurfInfoOut->pitch; >> + surf_level->nblk_y = AddrSurfInfoOut->height; >> + if (type == RADEON_SURF_TYPE_3D) >> + surf_level->nblk_z = AddrSurfInfoOut->depth; >> + else >> + surf_level->nblk_z = 1; >> + >> + switch (AddrSurfInfoOut->tileMode) { >> + case ADDR_TM_LINEAR_ALIGNED: >> + surf_level->mode = RADEON_SURF_MODE_LINEAR_ALIGNED; >> + break; >> + case ADDR_TM_1D_TILED_THIN1: >> + surf_level->mode = RADEON_SURF_MODE_1D; >> + break; >> + case ADDR_TM_2D_TILED_THIN1: >> + surf_level->mode = RADEON_SURF_MODE_2D; >> + break; >> + default: >> + assert(0); >> + } >> + >> + if (is_stencil) >> + surf->stencil_tiling_index[level] = AddrSurfInfoOut->tileIndex; >> + else >> + surf->tiling_index[level] = AddrSurfInfoOut->tileIndex; >> + >> + surf->bo_size = surf_level->offset + AddrSurfInfoOut->surfSize; >> + >> + /* Clear DCC fields at the beginning. */ >> + surf_level->dcc_offset = 0; >> + surf_level->dcc_enabled = false; >> + >> + /* The previous level's flag tells us if we can use DCC for this >> level. */ >> + if (AddrSurfInfoIn->flags.dccCompatible && >> + (level == 0 || AddrDccOut->subLvlCompressible)) { >> + AddrDccIn->colorSurfSize = AddrSurfInfoOut->surfSize; >> + AddrDccIn->tileMode = AddrSurfInfoOut->tileMode; >> + AddrDccIn->tileInfo = *AddrSurfInfoOut->pTileInfo; >> + AddrDccIn->tileIndex = AddrSurfInfoOut->tileIndex; >> + AddrDccIn->macroModeIndex = AddrSurfInfoOut->macroModeIndex; >> + >> + ret = AddrComputeDccInfo(addrlib, >> + AddrDccIn, >> + AddrDccOut); >> + >> + if (ret == ADDR_OK) { >> + surf_level->dcc_offset = surf->dcc_size; >> + surf_level->dcc_fast_clear_size = >> AddrDccOut->dccFastClearSize; >> + surf_level->dcc_enabled = true; >> + surf->dcc_size = surf_level->dcc_offset + >> AddrDccOut->dccRamSize; >> + surf->dcc_alignment = MAX(surf->dcc_alignment, >> AddrDccOut->dccRamBaseAlign); >> + } >> + } >> + >> + return 0; >> +} >> + >> +static void radv_set_micro_tile_mode(struct radeon_surf *surf, >> + struct radeon_info *info) >> +{ >> + uint32_t tile_mode = >> info->si_tile_mode_array[surf->tiling_index[0]]; >> + >> + if (info->chip_class >= CIK) >> + surf->micro_tile_mode = G_009910_MICRO_TILE_MODE_NEW(tile_mode); >> + else >> + surf->micro_tile_mode = G_009910_MICRO_TILE_MODE(tile_mode); >> +} >> + >> + >> +static int radv_amdgpu_winsys_surface_init(struct radeon_winsys *_ws, >> + struct radeon_surf *surf) >> +{ >> + struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws); >> + unsigned level, mode, type; >> + bool compressed; >> + ADDR_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn = {0}; >> + ADDR_COMPUTE_SURFACE_INFO_OUTPUT AddrSurfInfoOut = {0}; >> + ADDR_COMPUTE_DCCINFO_INPUT AddrDccIn = {0}; >> + ADDR_COMPUTE_DCCINFO_OUTPUT AddrDccOut = {0}; >> + ADDR_TILEINFO AddrTileInfoIn = {0}; >> + ADDR_TILEINFO AddrTileInfoOut = {0}; >> + int r; >> + >> + r = radv_amdgpu_surface_sanity(surf); >> + if (r) >> + return r; >> + >> + AddrSurfInfoIn.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT); >> + AddrSurfInfoOut.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT); >> + AddrDccIn.size = sizeof(ADDR_COMPUTE_DCCINFO_INPUT); >> + AddrDccOut.size = sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT); >> + AddrSurfInfoOut.pTileInfo = &AddrTileInfoOut; >> + >> + type = RADEON_SURF_GET(surf->flags, TYPE); >> + mode = RADEON_SURF_GET(surf->flags, MODE); >> + compressed = surf->blk_w == 4 && surf->blk_h == 4; >> + >> + /* MSAA and FMASK require 2D tiling. */ >> + if (surf->nsamples > 1 || >> + (surf->flags & RADEON_SURF_FMASK)) >> + mode = RADEON_SURF_MODE_2D; >> + >> + /* DB doesn't support linear layouts. */ >> + if (surf->flags & (RADEON_SURF_Z_OR_SBUFFER) && >> + mode < RADEON_SURF_MODE_1D) >> + mode = RADEON_SURF_MODE_1D; >> + >> + /* Set the requested tiling mode. */ >> + switch (mode) { >> + case RADEON_SURF_MODE_LINEAR_ALIGNED: >> + AddrSurfInfoIn.tileMode = ADDR_TM_LINEAR_ALIGNED; >> + break; >> + case RADEON_SURF_MODE_1D: >> + AddrSurfInfoIn.tileMode = ADDR_TM_1D_TILED_THIN1; >> + break; >> + case RADEON_SURF_MODE_2D: >> + AddrSurfInfoIn.tileMode = ADDR_TM_2D_TILED_THIN1; >> + break; >> + default: >> + assert(0); >> + } >> + >> + /* The format must be set correctly for the allocation of compressed >> + * textures to work. In other cases, setting the bpp is >> sufficient. */ >> + if (compressed) { >> + switch (surf->bpe) { >> + case 8: >> + AddrSurfInfoIn.format = ADDR_FMT_BC1; >> + break; >> + case 16: >> + AddrSurfInfoIn.format = ADDR_FMT_BC3; >> + break; >> + default: >> + assert(0); >> + } >> + } >> + else { >> + AddrDccIn.bpp = AddrSurfInfoIn.bpp = surf->bpe * 8; >> + } >> + >> + AddrDccIn.numSamples = AddrSurfInfoIn.numSamples = surf->nsamples; >> + AddrSurfInfoIn.tileIndex = -1; >> + >> + /* Set the micro tile type. */ >> + if (surf->flags & RADEON_SURF_SCANOUT) >> + AddrSurfInfoIn.tileType = ADDR_DISPLAYABLE; >> + else if (surf->flags & RADEON_SURF_Z_OR_SBUFFER) >> + AddrSurfInfoIn.tileType = ADDR_DEPTH_SAMPLE_ORDER; >> + else >> + AddrSurfInfoIn.tileType = ADDR_NON_DISPLAYABLE; >> + >> + AddrSurfInfoIn.flags.color = !(surf->flags & >> RADEON_SURF_Z_OR_SBUFFER); >> + AddrSurfInfoIn.flags.depth = (surf->flags & RADEON_SURF_ZBUFFER) >> != 0; >> + AddrSurfInfoIn.flags.cube = type == RADEON_SURF_TYPE_CUBEMAP; >> + AddrSurfInfoIn.flags.display = (surf->flags & >> RADEON_SURF_SCANOUT) != 0; >> + AddrSurfInfoIn.flags.pow2Pad = surf->last_level > 0; >> + AddrSurfInfoIn.flags.degrade4Space = 1; >> + >> + /* DCC notes: >> + * - If we add MSAA support, keep in mind that CB can't >> decompress 8bpp >> + * with samples >= 4. >> + * - Mipmapped array textures have low performance (discovered by >> a closed >> + * driver team). >> + */ >> + AddrSurfInfoIn.flags.dccCompatible = !(surf->flags & >> RADEON_SURF_Z_OR_SBUFFER) && >> + !(surf->flags & RADEON_SURF_DISABLE_DCC) && >> + !compressed && AddrDccIn.numSamples <= 1 && >> + ((surf->array_size == 1 && surf->npix_z == 1) || >> + surf->last_level == 0); >> + >> + AddrSurfInfoIn.flags.noStencil = (surf->flags & >> RADEON_SURF_SBUFFER) == 0; >> + AddrSurfInfoIn.flags.compressZ = AddrSurfInfoIn.flags.depth; >> + >> + /* noStencil = 0 can result in a depth part that is incompatible >> with >> + * mipmapped texturing. So set noStencil = 1 when mipmaps are >> requested (in >> + * this case, we may end up setting stencil_adjusted). >> + * >> + * TODO: update addrlib to a newer version, remove this, and >> + * use flags.matchStencilTileCfg = 1 as an alternative fix. >> + */ >> + if (surf->last_level > 0) >> + AddrSurfInfoIn.flags.noStencil = 1; >> + >> + /* Set preferred macrotile parameters. This is usually required >> + * for shared resources. This is for 2D tiling only. */ >> + if (AddrSurfInfoIn.tileMode >= ADDR_TM_2D_TILED_THIN1 && >> + surf->bankw && surf->bankh && surf->mtilea && >> surf->tile_split) { >> + /* If any of these parameters are incorrect, the calculation >> + * will fail. */ >> + AddrTileInfoIn.banks = surf->num_banks; >> + AddrTileInfoIn.bankWidth = surf->bankw; >> + AddrTileInfoIn.bankHeight = surf->bankh; >> + AddrTileInfoIn.macroAspectRatio = surf->mtilea; >> + AddrTileInfoIn.tileSplitBytes = surf->tile_split; >> + AddrTileInfoIn.pipeConfig = surf->pipe_config + 1; /* +1 >> compared to GB_TILE_MODE */ >> + AddrSurfInfoIn.flags.degrade4Space = 0; >> + AddrSurfInfoIn.pTileInfo = &AddrTileInfoIn; >> + >> + /* If AddrSurfInfoIn.pTileInfo is set, Addrlib doesn't set >> + * the tile index, because we are expected to know it if >> + * we know the other parameters. >> + * >> + * This is something that can easily be fixed in Addrlib. >> + * For now, just figure it out here. >> + * Note that only 2D_TILE_THIN1 is handled here. >> + */ >> + assert(!(surf->flags & RADEON_SURF_Z_OR_SBUFFER)); >> + assert(AddrSurfInfoIn.tileMode == ADDR_TM_2D_TILED_THIN1); >> + >> + if (ws->info.chip_class == SI) { >> + if (AddrSurfInfoIn.tileType == ADDR_DISPLAYABLE) { >> + if (surf->bpe == 2) >> + AddrSurfInfoIn.tileIndex = 11; /* 16bpp */ >> + else >> + AddrSurfInfoIn.tileIndex = 12; /* 32bpp */ >> + } else { >> + if (surf->bpe == 1) >> + AddrSurfInfoIn.tileIndex = 14; /* 8bpp */ >> + else if (surf->bpe == 2) >> + AddrSurfInfoIn.tileIndex = 15; /* 16bpp */ >> + else if (surf->bpe == 4) >> + AddrSurfInfoIn.tileIndex = 16; /* 32bpp */ >> + else >> + AddrSurfInfoIn.tileIndex = 17; /* 64bpp (and >> 128bpp) */ >> + } >> + } else { >> + if (AddrSurfInfoIn.tileType == ADDR_DISPLAYABLE) >> + AddrSurfInfoIn.tileIndex = 10; /* 2D displayable */ >> + else >> + AddrSurfInfoIn.tileIndex = 14; /* 2D non-displayable */ >> + } >> + } >> + >> + surf->bo_size = 0; >> + surf->dcc_size = 0; >> + surf->dcc_alignment = 1; >> + >> + /* Calculate texture layout information. */ >> + for (level = 0; level <= surf->last_level; level++) { >> + r = radv_compute_level(ws->addrlib, surf, false, level, type, >> compressed, >> + &AddrSurfInfoIn, &AddrSurfInfoOut, &AddrDccIn, >> &AddrDccOut); >> + if (r) >> + return r; >> + >> + if (level == 0) { >> + surf->bo_alignment = AddrSurfInfoOut.baseAlign; >> + surf->pipe_config = AddrSurfInfoOut.pTileInfo->pipeConfig >> - 1; >> + radv_set_micro_tile_mode(surf, &ws->info); >> + >> + /* For 2D modes only. */ >> + if (AddrSurfInfoOut.tileMode >= ADDR_TM_2D_TILED_THIN1) { >> + surf->bankw = AddrSurfInfoOut.pTileInfo->bankWidth; >> + surf->bankh = AddrSurfInfoOut.pTileInfo->bankHeight; >> + surf->mtilea = >> AddrSurfInfoOut.pTileInfo->macroAspectRatio; >> + surf->tile_split = >> AddrSurfInfoOut.pTileInfo->tileSplitBytes; >> + surf->num_banks = AddrSurfInfoOut.pTileInfo->banks; >> + surf->macro_tile_index = AddrSurfInfoOut.macroModeIndex; >> + } else { >> + surf->macro_tile_index = 0; >> + } >> + } >> + } >> + >> + /* Calculate texture layout information for stencil. */ >> + if (surf->flags & RADEON_SURF_SBUFFER) { >> + AddrSurfInfoIn.bpp = 8; >> + AddrSurfInfoIn.flags.depth = 0; >> + AddrSurfInfoIn.flags.stencil = 1; >> + /* This will be ignored if AddrSurfInfoIn.pTileInfo is NULL. */ >> + AddrTileInfoIn.tileSplitBytes = surf->stencil_tile_split; >> + >> + for (level = 0; level <= surf->last_level; level++) { >> + r = radv_compute_level(ws->addrlib, surf, true, level, >> type, compressed, >> + &AddrSurfInfoIn, &AddrSurfInfoOut, >> &AddrDccIn, &AddrDccOut); >> + if (r) >> + return r; >> + >> + /* DB uses the depth pitch for both stencil and depth. */ >> + if (surf->stencil_level[level].nblk_x != >> surf->level[level].nblk_x) >> + surf->stencil_adjusted = true; >> + >> + if (level == 0) { >> + /* For 2D modes only. */ >> + if (AddrSurfInfoOut.tileMode >= >> ADDR_TM_2D_TILED_THIN1) { >> + surf->stencil_tile_split = >> + AddrSurfInfoOut.pTileInfo->tileSplitBytes; >> + } >> + } >> + } >> + } >> + >> + /* Recalculate the whole DCC miptree size including disabled levels. >> + * This is what addrlib does, but calling addrlib would be a lot >> more >> + * complicated. >> + */ >> +#if 0 >> + if (surf->dcc_size && surf->last_level > 0) { >> + surf->dcc_size = align64(surf->bo_size >> 8, >> + ws->info.pipe_interleave_bytes * >> + ws->info.num_tile_pipes); >> + } >> +#endif >> + return 0; >> +} >> + >> +static int radv_amdgpu_winsys_surface_best(struct radeon_winsys *rws, >> + struct radeon_surf *surf) >> +{ >> + return 0; >> +} >> + >> +void radv_amdgpu_surface_init_functions(struct radv_amdgpu_winsys *ws) >> +{ >> + ws->base.surface_init = radv_amdgpu_winsys_surface_init; >> + ws->base.surface_best = radv_amdgpu_winsys_surface_best; >> +} >> diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_surface.h >> b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_surface.h >> new file mode 100644 >> index 0000000..acc12af >> --- /dev/null >> +++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_surface.h >> @@ -0,0 +1,29 @@ >> +/* >> + * Copyright © 2016 Red Hat. >> + * Copyright © 2016 Bas Nieuwenhuizen >> + * >> + * 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, >> sublicense, >> + * 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 above copyright notice and this permission notice (including >> the next >> + * paragraph) shall be included in all copies or substantial portions >> of the >> + * Software. >> + * >> + * 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 NONINFRINGEMENT. IN NO EVENT >> SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS 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. >> + */ >> +#pragma once >> + >> +#include <amdgpu.h> >> + >> +void radv_amdgpu_surface_init_functions(struct radv_amdgpu_winsys *ws); >> +ADDR_HANDLE radv_amdgpu_addr_create(struct amdgpu_gpu_info *amdinfo, >> int family, int rev_id, enum chip_class chip_class); >> diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.c >> b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.c >> new file mode 100644 >> index 0000000..f8c0375 >> --- /dev/null >> +++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.c >> @@ -0,0 +1,359 @@ >> +/* >> + * Copyright © 2016 Red Hat. >> + * Copyright © 2016 Bas Nieuwenhuizen >> + * based on amdgpu winsys. >> + * Copyright © 2011 Marek Olšák <mar...@gmail.com> >> + * Copyright © 2015 Advanced Micro Devices, Inc. >> + * >> + * 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, >> sublicense, >> + * 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 above copyright notice and this permission notice (including >> the next >> + * paragraph) shall be included in all copies or substantial portions >> of the >> + * Software. >> + * >> + * 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 NONINFRINGEMENT. IN NO EVENT >> SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS 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. >> + */ >> +#include "radv_amdgpu_winsys.h" >> +#include "radv_amdgpu_winsys_public.h" >> +#include "radv_amdgpu_surface.h" >> +#include "amdgpu_id.h" >> +#include "xf86drm.h" >> +#include <stdio.h> >> +#include <stdlib.h> >> +#include <string.h> >> +#include <amdgpu_drm.h> >> +#include <assert.h> >> +#include "radv_amdgpu_cs.h" >> +#include "radv_amdgpu_bo.h" >> +#include "radv_amdgpu_surface.h" >> +#define CIK_TILE_MODE_COLOR_2D 14 >> + >> +#define CIK__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f) >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P2 0 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16 4 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16 5 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32 6 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32 7 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16 16 >> +#define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16 17 >> + >> +static unsigned radv_cik_get_num_tile_pipes(struct amdgpu_gpu_info >> *info) >> +{ >> + unsigned mode2d = info->gb_tile_mode[CIK_TILE_MODE_COLOR_2D]; >> + >> + switch (CIK__GB_TILE_MODE__PIPE_CONFIG(mode2d)) { >> + case CIK__PIPE_CONFIG__ADDR_SURF_P2: >> + return 2; >> + case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16: >> + case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16: >> + case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32: >> + case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32: >> + return 4; >> + case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16: >> + case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16: >> + case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16: >> + case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16: >> + case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16: >> + case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32: >> + case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32: >> + return 8; >> + case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16: >> + case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16: >> + return 16; >> + default: >> + fprintf(stderr, "Invalid CIK pipe configuration, assuming >> P2\n"); >> + assert(!"this should never occur"); >> + return 2; >> + } >> +} >> + >> +static const char * >> +get_chip_name(enum radeon_family family) >> +{ >> + switch (family) { >> + case CHIP_TAHITI: return "AMD RADV TAHITI"; >> + case CHIP_PITCAIRN: return "AMD RADV PITCAIRN"; >> + case CHIP_VERDE: return "AMD RADV CAPE VERDE"; >> + case CHIP_OLAND: return "AMD RADV OLAND"; >> + case CHIP_HAINAN: return "AMD RADV HAINAN"; >> + case CHIP_BONAIRE: return "AMD RADV BONAIRE"; >> + case CHIP_KAVERI: return "AMD RADV KAVERI"; >> + case CHIP_KABINI: return "AMD RADV KABINI"; >> + case CHIP_HAWAII: return "AMD RADV HAWAII"; >> + case CHIP_MULLINS: return "AMD RADV MULLINS"; >> + case CHIP_TONGA: return "AMD RADV TONGA"; >> + case CHIP_ICELAND: return "AMD RADV ICELAND"; >> + case CHIP_CARRIZO: return "AMD RADV CARRIZO"; >> + case CHIP_FIJI: return "AMD RADV FIJI"; >> + case CHIP_POLARIS10: return "AMD RADV POLARIS10"; >> + case CHIP_POLARIS11: return "AMD RADV POLARIS11"; >> + case CHIP_STONEY: return "AMD RADV STONEY"; >> + default: return "AMD RADV unknown"; >> + } >> +} >> + >> + >> +static bool >> +do_winsys_init(struct radv_amdgpu_winsys *ws, int fd) >> +{ >> + struct amdgpu_buffer_size_alignments alignment_info = {}; >> + struct amdgpu_heap_info vram, gtt; >> + struct drm_amdgpu_info_hw_ip dma = {}; >> + drmDevicePtr devinfo; >> + int r; >> + int i, j; >> + /* Get PCI info. */ >> + r = drmGetDevice(fd, &devinfo); >> + if (r) { >> + fprintf(stderr, "amdgpu: drmGetDevice failed.\n"); >> + goto fail; >> + } >> + ws->info.pci_domain = devinfo->businfo.pci->domain; >> + ws->info.pci_bus = devinfo->businfo.pci->bus; >> + ws->info.pci_dev = devinfo->businfo.pci->dev; >> + ws->info.pci_func = devinfo->businfo.pci->func; >> + drmFreeDevice(&devinfo); >> + >> + /* Query hardware and driver information. */ >> + r = amdgpu_query_gpu_info(ws->dev, &ws->amdinfo); >> + if (r) { >> + fprintf(stderr, "amdgpu: amdgpu_query_gpu_info failed.\n"); >> + goto fail; >> + } >> + >> + r = amdgpu_query_buffer_size_alignment(ws->dev, &alignment_info); >> + if (r) { >> + fprintf(stderr, "amdgpu: amdgpu_query_buffer_size_alignment >> failed.\n"); >> + goto fail; >> + } >> + >> + r = amdgpu_query_heap_info(ws->dev, AMDGPU_GEM_DOMAIN_VRAM, 0, >> &vram); >> + if (r) { >> + fprintf(stderr, "amdgpu: amdgpu_query_heap_info(vram) >> failed.\n"); >> + goto fail; >> + } >> + >> + r = amdgpu_query_heap_info(ws->dev, AMDGPU_GEM_DOMAIN_GTT, 0, >t); >> + if (r) { >> + fprintf(stderr, "amdgpu: amdgpu_query_heap_info(gtt) >> failed.\n"); >> + goto fail; >> + } >> + >> + r = amdgpu_query_hw_ip_info(ws->dev, AMDGPU_HW_IP_DMA, 0, &dma); >> + if (r) { >> + fprintf(stderr, "amdgpu: amdgpu_query_hw_ip_info(dma) >> failed.\n"); >> + goto fail; >> + } >> + ws->info.pci_id = ws->amdinfo.asic_id; /* TODO: is this correct? */ >> + ws->info.vce_harvest_config = ws->amdinfo.vce_harvest_config; >> + >> + switch (ws->info.pci_id) { >> +#define CHIPSET(pci_id, name, cfamily) case pci_id: ws->info.family = >> CHIP_##cfamily; break; >> +#include "pci_ids/radeonsi_pci_ids.h" >> +#undef CHIPSET >> + default: >> + fprintf(stderr, "amdgpu: Invalid PCI ID.\n"); >> + goto fail; >> + } >> + >> + if (ws->info.family >= CHIP_TONGA) >> + ws->info.chip_class = VI; >> + else if (ws->info.family >= CHIP_BONAIRE) >> + ws->info.chip_class = CIK; >> + else if (ws->info.family >= CHIP_TAHITI) >> + ws->info.chip_class = SI; >> + else { >> + fprintf(stderr, "amdgpu: Unknown family.\n"); >> + goto fail; >> + } >> + >> + /* family and rev_id are for addrlib */ >> + switch (ws->info.family) { >> + case CHIP_TAHITI: >> + ws->family = FAMILY_SI; >> + ws->rev_id = SI_TAHITI_P_A0; >> + break; >> + case CHIP_PITCAIRN: >> + ws->family = FAMILY_SI; >> + ws->rev_id = SI_PITCAIRN_PM_A0; >> + break; >> + case CHIP_VERDE: >> + ws->family = FAMILY_SI; >> + ws->rev_id = SI_CAPEVERDE_M_A0; >> + break; >> + case CHIP_OLAND: >> + ws->family = FAMILY_SI; >> + ws->rev_id = SI_OLAND_M_A0; >> + break; >> + case CHIP_HAINAN: >> + ws->family = FAMILY_SI; >> + ws->rev_id = SI_HAINAN_V_A0; >> + break; >> + case CHIP_BONAIRE: >> + ws->family = FAMILY_CI; >> + ws->rev_id = CI_BONAIRE_M_A0; >> + break; >> + case CHIP_KAVERI: >> + ws->family = FAMILY_KV; >> + ws->rev_id = KV_SPECTRE_A0; >> + break; >> + case CHIP_KABINI: >> + ws->family = FAMILY_KV; >> + ws->rev_id = KB_KALINDI_A0; >> + break; >> + case CHIP_HAWAII: >> + ws->family = FAMILY_CI; >> + ws->rev_id = CI_HAWAII_P_A0; >> + break; >> + case CHIP_MULLINS: >> + ws->family = FAMILY_KV; >> + ws->rev_id = ML_GODAVARI_A0; >> + break; >> + case CHIP_TONGA: >> + ws->family = FAMILY_VI; >> + ws->rev_id = VI_TONGA_P_A0; >> + break; >> + case CHIP_ICELAND: >> + ws->family = FAMILY_VI; >> + ws->rev_id = VI_ICELAND_M_A0; >> + break; >> + case CHIP_CARRIZO: >> + ws->family = FAMILY_CZ; >> + ws->rev_id = CARRIZO_A0; >> + break; >> + case CHIP_STONEY: >> + ws->family = FAMILY_CZ; >> + ws->rev_id = STONEY_A0; >> + break; >> + case CHIP_FIJI: >> + ws->family = FAMILY_VI; >> + ws->rev_id = VI_FIJI_P_A0; >> + break; >> + case CHIP_POLARIS10: >> + ws->family = FAMILY_VI; >> + ws->rev_id = VI_POLARIS10_P_A0; >> + break; >> + case CHIP_POLARIS11: >> + ws->family = FAMILY_VI; >> + ws->rev_id = VI_POLARIS11_M_A0; >> + break; >> + default: >> + fprintf(stderr, "amdgpu: Unknown family.\n"); >> + goto fail; >> + } >> + >> + ws->addrlib = radv_amdgpu_addr_create(&ws->amdinfo, ws->family, >> ws->rev_id, ws->info.chip_class); >> + if (!ws->addrlib) { >> + fprintf(stderr, "amdgpu: Cannot create addrlib.\n"); >> + goto fail; >> + } >> + /* Set hardware information. */ >> + ws->info.name = get_chip_name(ws->info.family); >> + ws->info.gart_size = gtt.heap_size; >> + ws->info.vram_size = vram.heap_size; >> + /* convert the shader clock from KHz to MHz */ >> + ws->info.max_shader_clock = ws->amdinfo.max_engine_clk / 1000; >> + ws->info.max_se = ws->amdinfo.num_shader_engines; >> + ws->info.max_sh_per_se = ws->amdinfo.num_shader_arrays_per_engine; >> + ws->info.has_uvd = 0; >> + ws->info.vce_fw_version = 0; >> + ws->info.has_userptr = TRUE; >> + ws->info.num_render_backends = ws->amdinfo.rb_pipes; >> + ws->info.clock_crystal_freq = ws->amdinfo.gpu_counter_freq; >> + ws->info.num_tile_pipes = radv_cik_get_num_tile_pipes(&ws->amdinfo); >> + ws->info.pipe_interleave_bytes = 256 << ((ws->amdinfo.gb_addr_cfg >> >> 4) & 0x7); >> + ws->info.has_virtual_memory = TRUE; >> + ws->info.has_sdma = dma.available_rings != 0; >> + >> + /* Get the number of good compute units. */ >> + ws->info.num_good_compute_units = 0; >> + for (i = 0; i < ws->info.max_se; i++) >> + for (j = 0; j < ws->info.max_sh_per_se; j++) >> + ws->info.num_good_compute_units += >> + util_bitcount(ws->amdinfo.cu_bitmap[i][j]); >> + >> + memcpy(ws->info.si_tile_mode_array, ws->amdinfo.gb_tile_mode, >> + sizeof(ws->amdinfo.gb_tile_mode)); >> + ws->info.enabled_rb_mask = ws->amdinfo.enabled_rb_pipes_mask; >> + >> + memcpy(ws->info.cik_macrotile_mode_array, >> ws->amdinfo.gb_macro_tile_mode, >> + sizeof(ws->amdinfo.gb_macro_tile_mode)); >> + >> + ws->info.gart_page_size = alignment_info.size_remote; >> + >> + if (ws->info.chip_class == SI) >> + ws->info.gfx_ib_pad_with_type2 = TRUE; >> + >> + ws->use_ib_bos = ws->family >= FAMILY_CI; >> + return true; >> +fail: >> + return false; >> +} >> + >> +static void radv_amdgpu_winsys_query_info(struct radeon_winsys *rws, >> + struct radeon_info *info) >> +{ >> + *info = ((struct radv_amdgpu_winsys *)rws)->info; >> +} >> + >> +static void radv_amdgpu_winsys_destroy(struct radeon_winsys *rws) >> +{ >> + struct radv_amdgpu_winsys *ws = (struct radv_amdgpu_winsys*)rws; >> + >> + AddrDestroy(ws->addrlib); >> + amdgpu_device_deinitialize(ws->dev); >> + FREE(rws); >> +} >> + >> +struct radeon_winsys * >> +radv_amdgpu_winsys_create(int fd) >> +{ >> + uint32_t drm_major, drm_minor, r; >> + amdgpu_device_handle dev; >> + struct radv_amdgpu_winsys *ws; >> + >> + r = amdgpu_device_initialize(fd, &drm_major, &drm_minor, &dev); >> + if (r) >> + return NULL; >> + >> + ws = calloc(1, sizeof(struct radv_amdgpu_winsys)); >> + if (!ws) >> + return NULL; >> + >> + >> + ws->dev = dev; >> + ws->info.drm_major = drm_major; >> + ws->info.drm_minor = drm_minor; >> + if (!do_winsys_init(ws, fd)) >> + goto fail; >> + >> + ws->debug_all_bos = getenv("RADV_DEBUG_ALL_BOS") ? true : false; >> + LIST_INITHEAD(&ws->global_bo_list); >> + pthread_mutex_init(&ws->global_bo_list_lock, NULL); >> + ws->base.query_info = radv_amdgpu_winsys_query_info; >> + ws->base.destroy = radv_amdgpu_winsys_destroy; >> + radv_amdgpu_bo_init_functions(ws); >> + radv_amdgpu_cs_init_functions(ws); >> + radv_amdgpu_surface_init_functions(ws); >> + return &ws->base; >> +fail: >> + return NULL; >> +} >> diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.h >> b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.h >> new file mode 100644 >> index 0000000..85e459d >> --- /dev/null >> +++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.h >> @@ -0,0 +1,32 @@ >> + >> +#pragma once >> + >> +#include "radv_radeon_winsys.h" >> +#include "addrlib/addrinterface.h" >> +#include <amdgpu.h> >> +#include "util/list.h" >> + >> +struct radv_amdgpu_winsys { >> + struct radeon_winsys base; >> + amdgpu_device_handle dev; >> + >> + struct radeon_info info; >> + struct amdgpu_gpu_info amdinfo; >> + ADDR_HANDLE addrlib; >> + >> + uint32_t rev_id; >> + unsigned family; >> + >> + bool debug_all_bos; >> + pthread_mutex_t global_bo_list_lock; >> + struct list_head global_bo_list; >> + unsigned num_buffers; >> + >> + bool use_ib_bos; >> +}; >> + >> +static inline struct radv_amdgpu_winsys * >> +radv_amdgpu_winsys(struct radeon_winsys *base) >> +{ >> + return (struct radv_amdgpu_winsys*)base; >> +} >> diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys_public.h >> b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys_public.h >> new file mode 100644 >> index 0000000..cf06601 >> --- /dev/null >> +++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys_public.h >> @@ -0,0 +1,30 @@ >> +/* >> + * Copyright © 2016 Red Hat. >> + * Copyright © 2016 Bas Nieuwenhuizen >> + * >> + * based on amdgpu winsys. >> + * Copyright © 2011 Marek Olšák <mar...@gmail.com> >> + * Copyright © 2015 Advanced Micro Devices, Inc. >> + * >> + * 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, >> sublicense, >> + * 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 above copyright notice and this permission notice (including >> the next >> + * paragraph) shall be included in all copies or substantial portions >> of the >> + * Software. >> + * >> + * 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 NONINFRINGEMENT. IN NO EVENT >> SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS 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. >> + */ >> +#pragma once >> + >> +struct radeon_winsys *radv_amdgpu_winsys_create(int fd); >> > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev
signature.asc
Description: OpenPGP digital signature
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev