Path: blob/21.2-virgl/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c
4566 views
1#include "i915_drm_winsys.h"2#include "util/u_memory.h"34#include "drm-uapi/i915_drm.h"5#include "i915/i915_debug.h"6#include <xf86drm.h>7#include <stdio.h>89#define BATCH_RESERVED 161011#define INTEL_DEFAULT_RELOCS 10012#define INTEL_MAX_RELOCS 4001314#define INTEL_BATCH_NO_CLIPRECTS 0x115#define INTEL_BATCH_CLIPRECTS 0x21617#undef INTEL_RUN_SYNC1819struct i915_drm_batchbuffer20{21struct i915_winsys_batchbuffer base;2223size_t actual_size;2425drm_intel_bo *bo;26};2728static inline struct i915_drm_batchbuffer *29i915_drm_batchbuffer(struct i915_winsys_batchbuffer *batch)30{31return (struct i915_drm_batchbuffer *)batch;32}3334static void35i915_drm_batchbuffer_reset(struct i915_drm_batchbuffer *batch)36{37struct i915_drm_winsys *idws = i915_drm_winsys(batch->base.iws);3839if (batch->bo)40drm_intel_bo_unreference(batch->bo);41batch->bo = drm_intel_bo_alloc(idws->gem_manager,42"gallium3d_batchbuffer",43batch->actual_size,444096);4546memset(batch->base.map, 0, batch->actual_size);47batch->base.ptr = batch->base.map;48batch->base.size = batch->actual_size - BATCH_RESERVED;49batch->base.relocs = 0;50}5152static struct i915_winsys_batchbuffer *53i915_drm_batchbuffer_create(struct i915_winsys *iws)54{55struct i915_drm_winsys *idws = i915_drm_winsys(iws);56struct i915_drm_batchbuffer *batch = CALLOC_STRUCT(i915_drm_batchbuffer);5758batch->actual_size = idws->max_batch_size;5960batch->base.map = MALLOC(batch->actual_size);61batch->base.ptr = NULL;62batch->base.size = 0;6364batch->base.relocs = 0;6566batch->base.iws = iws;6768i915_drm_batchbuffer_reset(batch);6970return &batch->base;71}7273static bool74i915_drm_batchbuffer_validate_buffers(struct i915_winsys_batchbuffer *batch,75struct i915_winsys_buffer **buffer,76int num_of_buffers)77{78struct i915_drm_batchbuffer *drm_batch = i915_drm_batchbuffer(batch);79drm_intel_bo *bos[num_of_buffers + 1];80int i, ret;8182bos[0] = drm_batch->bo;83for (i = 0; i < num_of_buffers; i++)84bos[i+1] = intel_bo(buffer[i]);8586ret = drm_intel_bufmgr_check_aperture_space(bos, num_of_buffers);87if (ret != 0)88return false;8990return true;91}9293static int94i915_drm_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch,95struct i915_winsys_buffer *buffer,96enum i915_winsys_buffer_usage usage,97unsigned pre_add, bool fenced)98{99struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch);100unsigned write_domain = 0;101unsigned read_domain = 0;102unsigned offset;103int ret = 0;104105switch (usage) {106case I915_USAGE_SAMPLER:107write_domain = 0;108read_domain = I915_GEM_DOMAIN_SAMPLER;109break;110case I915_USAGE_RENDER:111write_domain = I915_GEM_DOMAIN_RENDER;112read_domain = I915_GEM_DOMAIN_RENDER;113break;114case I915_USAGE_2D_TARGET:115write_domain = I915_GEM_DOMAIN_RENDER;116read_domain = I915_GEM_DOMAIN_RENDER;117break;118case I915_USAGE_2D_SOURCE:119write_domain = 0;120read_domain = I915_GEM_DOMAIN_RENDER;121break;122case I915_USAGE_VERTEX:123write_domain = 0;124read_domain = I915_GEM_DOMAIN_VERTEX;125break;126default:127assert(0);128return -1;129}130131offset = (unsigned)(batch->base.ptr - batch->base.map);132133if (fenced)134ret = drm_intel_bo_emit_reloc_fence(batch->bo, offset,135intel_bo(buffer), pre_add,136read_domain,137write_domain);138else139ret = drm_intel_bo_emit_reloc(batch->bo, offset,140intel_bo(buffer), pre_add,141read_domain,142write_domain);143144((uint32_t*)batch->base.ptr)[0] = intel_bo(buffer)->offset + pre_add;145batch->base.ptr += 4;146147if (!ret)148batch->base.relocs++;149150return ret;151}152153static void154i915_drm_throttle(struct i915_drm_winsys *idws)155{156drmIoctl(idws->fd, DRM_IOCTL_I915_GEM_THROTTLE, NULL);157}158159static void160i915_drm_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch,161struct pipe_fence_handle **fence,162enum i915_winsys_flush_flags flags)163{164struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch);165unsigned used;166int ret;167168/* MI_BATCH_BUFFER_END */169i915_winsys_batchbuffer_dword_unchecked(ibatch, (0xA<<23));170171used = batch->base.ptr - batch->base.map;172if (used & 4) {173/* MI_NOOP */174i915_winsys_batchbuffer_dword_unchecked(ibatch, 0);175used += 4;176}177178/* Do the sending to HW */179ret = drm_intel_bo_subdata(batch->bo, 0, used, batch->base.map);180if (ret == 0 && i915_drm_winsys(ibatch->iws)->send_cmd)181ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0);182183if (flags & I915_FLUSH_END_OF_FRAME)184i915_drm_throttle(i915_drm_winsys(ibatch->iws));185186if (ret != 0 || i915_drm_winsys(ibatch->iws)->dump_cmd) {187i915_dump_batchbuffer(ibatch);188assert(ret == 0);189}190191if (i915_drm_winsys(ibatch->iws)->dump_raw_file) {192FILE *file = fopen(i915_drm_winsys(ibatch->iws)->dump_raw_file, "a");193if (file) {194fwrite(batch->base.map, used, 1, file);195fclose(file);196}197}198199#ifdef INTEL_RUN_SYNC200drm_intel_bo_wait_rendering(batch->bo);201#endif202203if (fence) {204ibatch->iws->fence_reference(ibatch->iws, fence, NULL);205206#ifdef INTEL_RUN_SYNC207/* we run synced to GPU so just pass null */208(*fence) = i915_drm_fence_create(NULL);209#else210(*fence) = i915_drm_fence_create(batch->bo);211#endif212}213214i915_drm_batchbuffer_reset(batch);215}216217static void218i915_drm_batchbuffer_destroy(struct i915_winsys_batchbuffer *ibatch)219{220struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch);221222if (batch->bo)223drm_intel_bo_unreference(batch->bo);224225FREE(batch->base.map);226FREE(batch);227}228229void i915_drm_winsys_init_batchbuffer_functions(struct i915_drm_winsys *idws)230{231idws->base.batchbuffer_create = i915_drm_batchbuffer_create;232idws->base.validate_buffers = i915_drm_batchbuffer_validate_buffers;233idws->base.batchbuffer_reloc = i915_drm_batchbuffer_reloc;234idws->base.batchbuffer_flush = i915_drm_batchbuffer_flush;235idws->base.batchbuffer_destroy = i915_drm_batchbuffer_destroy;236}237238239