struct panfrost_shader_state *state,
uint64_t *outputs_written)
{
- struct panfrost_screen *screen = pan_screen(ctx->base.screen);
+ struct panfrost_device *dev = pan_device(ctx->base.screen);
uint8_t *dst;
nir_shader *s;
.alpha_ref = state->alpha_state.ref_value
};
- midgard_compile_shader_nir(s, &program, false, 0, screen->gpu_id,
+ midgard_compile_shader_nir(s, &program, false, 0, dev->gpu_id,
pan_debug & PAN_DBG_PRECOMPILE);
/* Prepare the compiled binary for upload */
* that's how I'd do it. */
if (size) {
- state->bo = panfrost_bo_create(screen, size, PAN_BO_EXECUTE);
+ state->bo = panfrost_bo_create(dev, size, PAN_BO_EXECUTE);
memcpy(state->bo->cpu, dst, size);
state->first_tag = program.first_tag;
} else {
enum pipe_format format,
unsigned rt)
{
- struct panfrost_screen *screen = pan_screen(ctx->base.screen);
+ struct panfrost_device *dev = pan_device(ctx->base.screen);
struct panfrost_blend_shader res;
res.ctx = ctx;
NIR_PASS_V(shader, nir_lower_blend, options);
- NIR_PASS_V(shader, nir_lower_framebuffer, format, screen->gpu_id);
+ NIR_PASS_V(shader, nir_lower_framebuffer, format, dev->gpu_id);
/* Compile the built shader */
panfrost_program program;
- midgard_compile_shader_nir(shader, &program, true, rt, screen->gpu_id, false);
+ midgard_compile_shader_nir(shader, &program, true, rt, dev->gpu_id, false);
/* Allow us to patch later */
res.patch_index = program.blend_patch_offset;
#include "drm-uapi/panfrost_drm.h"
#include "pan_bo.h"
-#include "pan_screen.h"
#include "pan_util.h"
#include "pandecode/decode.h"
*/
static struct panfrost_bo *
-panfrost_bo_alloc(struct panfrost_screen *screen, size_t size,
+panfrost_bo_alloc(struct panfrost_device *dev, size_t size,
uint32_t flags)
{
struct drm_panfrost_create_bo create_bo = { .size = size };
struct panfrost_bo *bo;
int ret;
- if (screen->kernel_version->version_major > 1 ||
- screen->kernel_version->version_minor >= 1) {
+ if (dev->kernel_version->version_major > 1 ||
+ dev->kernel_version->version_minor >= 1) {
if (flags & PAN_BO_GROWABLE)
create_bo.flags |= PANFROST_BO_HEAP;
if (!(flags & PAN_BO_EXECUTE))
create_bo.flags |= PANFROST_BO_NOEXEC;
}
- ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_CREATE_BO, &create_bo);
+ ret = drmIoctl(dev->fd, DRM_IOCTL_PANFROST_CREATE_BO, &create_bo);
if (ret) {
DBG("DRM_IOCTL_PANFROST_CREATE_BO failed: %m\n");
return NULL;
}
- bo = rzalloc(screen, struct panfrost_bo);
+ bo = rzalloc(dev->memctx, struct panfrost_bo);
assert(bo);
bo->size = create_bo.size;
bo->gpu = create_bo.offset;
bo->gem_handle = create_bo.handle;
bo->flags = flags;
- bo->screen = screen;
+ bo->dev = dev;
return bo;
}
struct drm_gem_close gem_close = { .handle = bo->gem_handle };
int ret;
- ret = drmIoctl(bo->screen->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+ ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
if (ret) {
fprintf(stderr, "DRM_IOCTL_GEM_CLOSE failed: %m\n");
assert(0);
/* The ioctl returns >= 0 value when the BO we are waiting for is ready
* -1 otherwise.
*/
- ret = drmIoctl(bo->screen->fd, DRM_IOCTL_PANFROST_WAIT_BO, &req);
+ ret = drmIoctl(bo->dev->fd, DRM_IOCTL_PANFROST_WAIT_BO, &req);
if (ret != -1) {
/* Set gpu_access to 0 so that the next call to bo_wait()
* doesn't have to call the WAIT_BO ioctl.
}
static struct list_head *
-pan_bucket(struct panfrost_screen *screen, unsigned size)
+pan_bucket(struct panfrost_device *dev, unsigned size)
{
- return &screen->bo_cache.buckets[pan_bucket_index(size)];
+ return &dev->bo_cache.buckets[pan_bucket_index(size)];
}
/* Tries to fetch a BO of sufficient size with the appropriate flags from the
* BO. */
static struct panfrost_bo *
-panfrost_bo_cache_fetch(struct panfrost_screen *screen,
+panfrost_bo_cache_fetch(struct panfrost_device *dev,
size_t size, uint32_t flags, bool dontwait)
{
- pthread_mutex_lock(&screen->bo_cache.lock);
- struct list_head *bucket = pan_bucket(screen, size);
+ pthread_mutex_lock(&dev->bo_cache.lock);
+ struct list_head *bucket = pan_bucket(dev, size);
struct panfrost_bo *bo = NULL;
/* Iterate the bucket looking for something suitable */
list_del(&entry->bucket_link);
list_del(&entry->lru_link);
- ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_MADVISE, &madv);
+ ret = drmIoctl(dev->fd, DRM_IOCTL_PANFROST_MADVISE, &madv);
if (!ret && !madv.retained) {
panfrost_bo_free(entry);
continue;
bo = entry;
break;
}
- pthread_mutex_unlock(&screen->bo_cache.lock);
+ pthread_mutex_unlock(&dev->bo_cache.lock);
return bo;
}
static void
-panfrost_bo_cache_evict_stale_bos(struct panfrost_screen *screen)
+panfrost_bo_cache_evict_stale_bos(struct panfrost_device *dev)
{
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
list_for_each_entry_safe(struct panfrost_bo, entry,
- &screen->bo_cache.lru, lru_link) {
+ &dev->bo_cache.lru, lru_link) {
/* We want all entries that have been used more than 1 sec
* ago to be dropped, others can be kept.
* Note the <= 2 check and not <= 1. It's here to account for
static bool
panfrost_bo_cache_put(struct panfrost_bo *bo)
{
- struct panfrost_screen *screen = bo->screen;
+ struct panfrost_device *dev = bo->dev;
if (bo->flags & PAN_BO_DONT_REUSE)
return false;
- pthread_mutex_lock(&screen->bo_cache.lock);
- struct list_head *bucket = pan_bucket(screen, bo->size);
+ pthread_mutex_lock(&dev->bo_cache.lock);
+ struct list_head *bucket = pan_bucket(dev, bo->size);
struct drm_panfrost_madvise madv;
struct timespec time;
madv.madv = PANFROST_MADV_DONTNEED;
madv.retained = 0;
- drmIoctl(screen->fd, DRM_IOCTL_PANFROST_MADVISE, &madv);
+ drmIoctl(dev->fd, DRM_IOCTL_PANFROST_MADVISE, &madv);
/* Add us to the bucket */
list_addtail(&bo->bucket_link, bucket);
/* Add us to the LRU list and update the last_used field. */
- list_addtail(&bo->lru_link, &screen->bo_cache.lru);
+ list_addtail(&bo->lru_link, &dev->bo_cache.lru);
clock_gettime(CLOCK_MONOTONIC, &time);
bo->last_used = time.tv_sec;
/* Let's do some cleanup in the BO cache while we hold the
* lock.
*/
- panfrost_bo_cache_evict_stale_bos(screen);
- pthread_mutex_unlock(&screen->bo_cache.lock);
+ panfrost_bo_cache_evict_stale_bos(dev);
+ pthread_mutex_unlock(&dev->bo_cache.lock);
return true;
}
void
panfrost_bo_cache_evict_all(
- struct panfrost_screen *screen)
+ struct panfrost_device *dev)
{
- pthread_mutex_lock(&screen->bo_cache.lock);
- for (unsigned i = 0; i < ARRAY_SIZE(screen->bo_cache.buckets); ++i) {
- struct list_head *bucket = &screen->bo_cache.buckets[i];
+ pthread_mutex_lock(&dev->bo_cache.lock);
+ for (unsigned i = 0; i < ARRAY_SIZE(dev->bo_cache.buckets); ++i) {
+ struct list_head *bucket = &dev->bo_cache.buckets[i];
list_for_each_entry_safe(struct panfrost_bo, entry, bucket,
bucket_link) {
panfrost_bo_free(entry);
}
}
- pthread_mutex_unlock(&screen->bo_cache.lock);
+ pthread_mutex_unlock(&dev->bo_cache.lock);
}
void
if (bo->cpu)
return;
- ret = drmIoctl(bo->screen->fd, DRM_IOCTL_PANFROST_MMAP_BO, &mmap_bo);
+ ret = drmIoctl(bo->dev->fd, DRM_IOCTL_PANFROST_MMAP_BO, &mmap_bo);
if (ret) {
fprintf(stderr, "DRM_IOCTL_PANFROST_MMAP_BO failed: %m\n");
assert(0);
}
bo->cpu = os_mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
- bo->screen->fd, mmap_bo.offset);
+ bo->dev->fd, mmap_bo.offset);
if (bo->cpu == MAP_FAILED) {
fprintf(stderr, "mmap failed: %p %m\n", bo->cpu);
assert(0);
}
struct panfrost_bo *
-panfrost_bo_create(struct panfrost_screen *screen, size_t size,
+panfrost_bo_create(struct panfrost_device *dev, size_t size,
uint32_t flags)
{
struct panfrost_bo *bo;
* and if that fails too, we try one more time to allocate from the
* cache, but this time we accept to wait.
*/
- bo = panfrost_bo_cache_fetch(screen, size, flags, true);
+ bo = panfrost_bo_cache_fetch(dev, size, flags, true);
if (!bo)
- bo = panfrost_bo_alloc(screen, size, flags);
+ bo = panfrost_bo_alloc(dev, size, flags);
if (!bo)
- bo = panfrost_bo_cache_fetch(screen, size, flags, false);
+ bo = panfrost_bo_cache_fetch(dev, size, flags, false);
if (!bo)
fprintf(stderr, "BO creation failed\n");
pipe_reference_init(&bo->reference, 1);
- pthread_mutex_lock(&screen->active_bos_lock);
- _mesa_set_add(bo->screen->active_bos, bo);
- pthread_mutex_unlock(&screen->active_bos_lock);
+ pthread_mutex_lock(&dev->active_bos_lock);
+ _mesa_set_add(bo->dev->active_bos, bo);
+ pthread_mutex_unlock(&dev->active_bos_lock);
return bo;
}
if (!pipe_reference(&bo->reference, NULL))
return;
- struct panfrost_screen *screen = bo->screen;
+ struct panfrost_device *dev = bo->dev;
- pthread_mutex_lock(&screen->active_bos_lock);
+ pthread_mutex_lock(&dev->active_bos_lock);
/* Someone might have imported this BO while we were waiting for the
* lock, let's make sure it's still not referenced before freeing it.
*/
if (!pipe_is_referenced(&bo->reference)) {
- _mesa_set_remove_key(bo->screen->active_bos, bo);
+ _mesa_set_remove_key(bo->dev->active_bos, bo);
/* When the reference count goes to zero, we need to cleanup */
panfrost_bo_munmap(bo);
if (!panfrost_bo_cache_put(bo))
panfrost_bo_free(bo);
}
- pthread_mutex_unlock(&screen->active_bos_lock);
+ pthread_mutex_unlock(&dev->active_bos_lock);
}
struct panfrost_bo *
-panfrost_bo_import(struct panfrost_screen *screen, int fd)
+panfrost_bo_import(struct panfrost_device *dev, int fd)
{
- struct panfrost_bo *bo, *newbo = rzalloc(screen, struct panfrost_bo);
+ struct panfrost_bo *bo, *newbo = rzalloc(dev->memctx, struct panfrost_bo);
struct drm_panfrost_get_bo_offset get_bo_offset = {0,};
struct set_entry *entry;
ASSERTED int ret;
unsigned gem_handle;
- newbo->screen = screen;
+ newbo->dev = dev;
- ret = drmPrimeFDToHandle(screen->fd, fd, &gem_handle);
+ ret = drmPrimeFDToHandle(dev->fd, fd, &gem_handle);
assert(!ret);
newbo->gem_handle = gem_handle;
- pthread_mutex_lock(&screen->active_bos_lock);
- entry = _mesa_set_search_or_add(screen->active_bos, newbo);
+ pthread_mutex_lock(&dev->active_bos_lock);
+ entry = _mesa_set_search_or_add(dev->active_bos, newbo);
assert(entry);
bo = (struct panfrost_bo *)entry->key;
if (newbo == bo) {
get_bo_offset.handle = gem_handle;
- ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_GET_BO_OFFSET, &get_bo_offset);
+ ret = drmIoctl(dev->fd, DRM_IOCTL_PANFROST_GET_BO_OFFSET, &get_bo_offset);
assert(!ret);
newbo->gpu = (mali_ptr) get_bo_offset.offset;
panfrost_bo_reference(bo);
assert(bo->cpu);
}
- pthread_mutex_unlock(&screen->active_bos_lock);
+ pthread_mutex_unlock(&dev->active_bos_lock);
return bo;
}
.flags = DRM_CLOEXEC,
};
- int ret = drmIoctl(bo->screen->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
+ int ret = drmIoctl(bo->dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
if (ret == -1)
return -1;
#include <panfrost-misc.h>
#include "pipe/p_state.h"
#include "util/list.h"
-
-struct panfrost_screen;
+#include "pan_device.h"
/* Flags for allocated memory */
struct pipe_reference reference;
- struct panfrost_screen *screen;
+ struct panfrost_device *dev;
/* Mapping for the entire object (all levels) */
uint8_t *cpu;
void
panfrost_bo_unreference(struct panfrost_bo *bo);
struct panfrost_bo *
-panfrost_bo_create(struct panfrost_screen *screen, size_t size,
+panfrost_bo_create(struct panfrost_device *dev, size_t size,
uint32_t flags);
void
panfrost_bo_mmap(struct panfrost_bo *bo);
struct panfrost_bo *
-panfrost_bo_import(struct panfrost_screen *screen, int fd);
+panfrost_bo_import(struct panfrost_device *dev, int fd);
int
panfrost_bo_export(struct panfrost_bo *bo);
void
-panfrost_bo_cache_evict_all(struct panfrost_screen *screen);
+panfrost_bo_cache_evict_all(struct panfrost_device *dev);
#endif /* __PAN_BO_H__ */
panfrost_vt_attach_framebuffer(struct panfrost_context *ctx,
struct midgard_payload_vertex_tiler *vt)
{
- struct panfrost_screen *screen = pan_screen(ctx->base.screen);
+ struct panfrost_device *dev = pan_device(ctx->base.screen);
struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
/* If we haven't, reserve space for the framebuffer */
if (!batch->framebuffer.gpu) {
- unsigned size = (screen->quirks & MIDGARD_SFBD) ?
+ unsigned size = (dev->quirks & MIDGARD_SFBD) ?
sizeof(struct mali_single_framebuffer) :
sizeof(struct mali_framebuffer);
batch->framebuffer = panfrost_allocate_transient(batch, size);
/* Tag the pointer */
- if (!(screen->quirks & MIDGARD_SFBD))
+ if (!(dev->quirks & MIDGARD_SFBD))
batch->framebuffer.gpu |= MALI_MFBD;
}
struct mali_shader_meta *fragmeta,
struct midgard_blend_rt *rts)
{
- const struct panfrost_screen *screen = pan_screen(ctx->base.screen);
+ const struct panfrost_device *dev = pan_device(ctx->base.screen);
SET_BIT(fragmeta->unknown2_4, MALI_NO_DITHER,
- (screen->quirks & MIDGARD_SFBD) && ctx->blend &&
+ (dev->quirks & MIDGARD_SFBD) && ctx->blend &&
!ctx->blend->base.dither);
/* Get blending setup */
break;
}
- if (screen->quirks & MIDGARD_SFBD) {
+ if (dev->quirks & MIDGARD_SFBD) {
/* When only a single render target platform is used, the blend
* information is inside the shader meta itself. We additionally
* need to signal CAN_DISCARD for nontrivial blend modes (so
struct mali_shader_meta *fragmeta,
struct midgard_blend_rt *rts)
{
- const struct panfrost_screen *screen = pan_screen(ctx->base.screen);
+ const struct panfrost_device *dev = pan_device(ctx->base.screen);
struct panfrost_shader_state *fs;
fs = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
* these earlier chips (perhaps this is a chicken bit of some kind).
* More investigation is needed. */
- SET_BIT(fragmeta->unknown2_4, 0x10, screen->quirks & MIDGARD_SFBD);
+ SET_BIT(fragmeta->unknown2_4, 0x10, dev->quirks & MIDGARD_SFBD);
/* Depending on whether it's legal to in the given shader, we try to
* enable early-z testing (or forward-pixel kill?) */
mali_ptr shader_ptr;
if (st == PIPE_SHADER_FRAGMENT) {
- struct panfrost_screen *screen = pan_screen(ctx->base.screen);
+ struct panfrost_device *dev = pan_device(ctx->base.screen);
unsigned rt_count = MAX2(ctx->pipe_framebuffer.nr_cbufs, 1);
size_t desc_size = sizeof(meta);
struct midgard_blend_rt rts[4];
panfrost_frag_shader_meta_init(ctx, &meta, rts);
- if (!(screen->quirks & MIDGARD_SFBD))
+ if (!(dev->quirks & MIDGARD_SFBD))
desc_size += sizeof(*rts) * rt_count;
xfer = panfrost_allocate_transient(batch, desc_size);
struct midgard_tiler_descriptor
panfrost_emit_midg_tiler(struct panfrost_batch *batch, unsigned vertex_count)
{
- struct panfrost_screen *screen = pan_screen(batch->ctx->base.screen);
- bool hierarchy = !(screen->quirks & MIDGARD_NO_HIER_TILING);
+ struct panfrost_device *device = pan_device(batch->ctx->base.screen);
+ bool hierarchy = !(device->quirks & MIDGARD_NO_HIER_TILING);
struct midgard_tiler_descriptor t = {0};
unsigned height = batch->key.height;
unsigned width = batch->key.width;
struct pipe_resource *texture,
const struct pipe_sampler_view *template)
{
- struct panfrost_screen *screen = pan_screen(pctx->screen);
+ struct panfrost_device *device = pan_device(pctx->screen);
struct panfrost_sampler_view *so = rzalloc(pctx, struct panfrost_sampler_view);
pipe_reference(NULL, &texture->reference);
template->u.tex.last_layer,
type, prsrc->layout);
- so->bo = panfrost_bo_create(screen, size, 0);
+ so->bo = panfrost_bo_create(device, size, 0);
panfrost_new_texture(
so->bo->cpu,
static void
panfrost_hint_afbc(
- struct panfrost_screen *screen,
+ struct panfrost_device *device,
const struct pipe_framebuffer_state *fb)
{
/* AFBC implemenation incomplete; hide it */
for (unsigned i = 0; i < fb->nr_cbufs; ++i) {
struct pipe_surface *surf = fb->cbufs[i];
struct panfrost_resource *rsrc = pan_resource(surf->texture);
- panfrost_resource_hint_layout(screen, rsrc, MALI_TEXTURE_AFBC, 1);
+ panfrost_resource_hint_layout(device, rsrc, MALI_TEXTURE_AFBC, 1);
}
/* Also hint it to the depth buffer */
if (fb->zsbuf) {
struct panfrost_resource *rsrc = pan_resource(fb->zsbuf->texture);
- panfrost_resource_hint_layout(screen, rsrc, MALI_TEXTURE_AFBC, 1);
+ panfrost_resource_hint_layout(device, rsrc, MALI_TEXTURE_AFBC, 1);
}
}
{
struct panfrost_context *ctx = pan_context(pctx);
- panfrost_hint_afbc(pan_screen(pctx->screen), fb);
+ panfrost_hint_afbc(pan_device(pctx->screen), fb);
util_copy_framebuffer_state(&ctx->pipe_framebuffer, fb);
ctx->batch = NULL;
panfrost_invalidate_frame(ctx);
/* Allocate a bo for the query results to be stored */
if (!query->bo) {
query->bo = panfrost_bo_create(
- pan_screen(ctx->base.screen),
+ pan_device(ctx->base.screen),
sizeof(unsigned), 0);
}
mali_ptr
panfrost_fragment_job(struct panfrost_batch *batch, bool has_draws)
{
- struct panfrost_screen *screen = pan_screen(batch->ctx->base.screen);
+ struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
- mali_ptr framebuffer = (screen->quirks & MIDGARD_SFBD) ?
+ mali_ptr framebuffer = (dev->quirks & MIDGARD_SFBD) ?
panfrost_sfbd_fragment(batch, has_draws) :
panfrost_mfbd_fragment(batch, has_draws);
pipe_reference_init(&fence->reference, 1);
fence->ctx = batch->ctx;
fence->batch = batch;
- ret = drmSyncobjCreate(pan_screen(batch->ctx->base.screen)->fd, 0,
+ ret = drmSyncobjCreate(pan_device(batch->ctx->base.screen)->fd, 0,
&fence->syncobj);
assert(!ret);
static void
panfrost_free_batch_fence(struct panfrost_batch_fence *fence)
{
- drmSyncobjDestroy(pan_screen(fence->ctx->base.screen)->fd,
+ drmSyncobjDestroy(pan_device(fence->ctx->base.screen)->fd,
fence->syncobj);
ralloc_free(fence);
}
if (fence->batch)
return false;
- int ret = drmSyncobjWait(pan_screen(fence->ctx->base.screen)->fd,
+ int ret = drmSyncobjWait(pan_device(fence->ctx->base.screen)->fd,
&fence->syncobj, 1, 0, 0, NULL);
/* Cache whether the fence was signaled */
{
struct panfrost_bo *bo;
- bo = panfrost_bo_create(pan_screen(batch->ctx->base.screen), size,
+ bo = panfrost_bo_create(pan_device(batch->ctx->base.screen), size,
create_flags);
panfrost_batch_add_bo(batch, bo, access_flags);
struct panfrost_bo *
panfrost_batch_get_tiler_dummy(struct panfrost_batch *batch)
{
- struct panfrost_screen *screen = pan_screen(batch->ctx->base.screen);
+ struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
uint32_t create_flags = 0;
if (batch->tiler_dummy)
return batch->tiler_dummy;
- if (!(screen->quirks & MIDGARD_NO_HIER_TILING))
+ if (!(dev->quirks & MIDGARD_NO_HIER_TILING))
create_flags = PAN_BO_INVISIBLE;
batch->tiler_dummy = panfrost_batch_create_bo(batch, 4096,
{
struct panfrost_context *ctx = batch->ctx;
struct pipe_context *gallium = (struct pipe_context *) ctx;
- struct panfrost_screen *screen = pan_screen(gallium->screen);
+ struct panfrost_device *dev = pan_device(gallium->screen);
struct drm_panfrost_submit submit = {0,};
uint32_t *bo_handles, *in_syncs = NULL;
bool is_fragment_shader;
}
submit.bo_handles = (u64) (uintptr_t) bo_handles;
- ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_SUBMIT, &submit);
+ ret = drmIoctl(dev->fd, DRM_IOCTL_PANFROST_SUBMIT, &submit);
free(bo_handles);
free(in_syncs);
/* Trace the job if we're doing that */
if (pan_debug & (PAN_DBG_TRACE | PAN_DBG_SYNC)) {
/* Wait so we can get errors reported back */
- drmSyncobjWait(screen->fd, &batch->out_sync->syncobj, 1,
+ drmSyncobjWait(dev->fd, &batch->out_sync->syncobj, 1,
INT64_MAX, 0, NULL);
/* Trace gets priority over sync */
bool minimal = !(pan_debug & PAN_DBG_TRACE);
- pandecode_jc(submit.jc, FALSE, screen->gpu_id, minimal);
+ pandecode_jc(submit.jc, FALSE, dev->gpu_id, minimal);
}
return 0;
if (batch->framebuffer.gpu && batch->first_job) {
struct panfrost_context *ctx = batch->ctx;
struct pipe_context *gallium = (struct pipe_context *) ctx;
- struct panfrost_screen *screen = pan_screen(gallium->screen);
+ struct panfrost_device *dev = pan_device(gallium->screen);
- if (screen->quirks & MIDGARD_SFBD)
+ if (dev->quirks & MIDGARD_SFBD)
panfrost_attach_sfbd(batch, ~0);
else
panfrost_attach_mfbd(batch, ~0);
if (!wait)
return;
- drmSyncobjWait(pan_screen(ctx->base.screen)->fd,
+ drmSyncobjWait(pan_device(ctx->base.screen)->fd,
util_dynarray_begin(&syncobjs),
util_dynarray_num_elements(&syncobjs, uint32_t),
INT64_MAX, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL, NULL);
batch->maxy = MIN2(batch->maxy, maxy);
}
-/* Are we currently rendering to the screen (rather than an FBO)? */
+/* Are we currently rendering to the dev (rather than an FBO)? */
bool
panfrost_batch_is_scanout(struct panfrost_batch *batch)
{
struct panfrost_context *ctx = batch->ctx;
struct pipe_context *gallium = (struct pipe_context *) ctx;
- struct panfrost_screen *screen = pan_screen(gallium->screen);
+ struct panfrost_device *dev = pan_device(gallium->screen);
unsigned width = batch->key.width;
unsigned height = batch->key.height;
.shared_memory = {
.stack_shift = shift,
- .scratchpad = panfrost_batch_get_scratchpad(batch, shift, screen->thread_tls_alloc, screen->core_count)->gpu,
+ .scratchpad = panfrost_batch_get_scratchpad(batch, shift, dev->thread_tls_alloc, dev->core_count)->gpu,
.shared_workgroup_count = ~0,
}
};
struct winsys_handle *whandle,
unsigned usage)
{
- struct panfrost_screen *screen = pan_screen(pscreen);
+ struct panfrost_device *dev = pan_device(pscreen);
struct panfrost_resource *rsc;
struct pipe_resource *prsc;
pipe_reference_init(&prsc->reference, 1);
prsc->screen = pscreen;
- rsc->bo = panfrost_bo_import(screen, whandle->handle);
+ rsc->bo = panfrost_bo_import(dev, whandle->handle);
rsc->internal_format = templat->format;
rsc->layout = MALI_TEXTURE_LINEAR;
rsc->slices[0].stride = whandle->stride;
rsc->slices[0].initialized = true;
panfrost_resource_reset_damage(rsc);
- if (screen->ro) {
+ if (dev->ro) {
rsc->scanout =
- renderonly_create_gpu_import_for_resource(prsc, screen->ro, NULL);
+ renderonly_create_gpu_import_for_resource(prsc, dev->ro, NULL);
/* failure is expected in some cases.. */
}
struct winsys_handle *handle,
unsigned usage)
{
- struct panfrost_screen *screen = pan_screen(pscreen);
+ struct panfrost_device *dev = pan_device(pscreen);
struct panfrost_resource *rsrc = (struct panfrost_resource *) pt;
struct renderonly_scanout *scanout = rsrc->scanout;
.flags = DRM_CLOEXEC,
};
- int ret = drmIoctl(screen->ro->kms_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
+ int ret = drmIoctl(dev->ro->kms_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
if (ret == -1)
return false;
panfrost_create_scanout_res(struct pipe_screen *screen,
const struct pipe_resource *template)
{
- struct panfrost_screen *pscreen = pan_screen(screen);
+ struct panfrost_device *dev = pan_device(screen);
struct pipe_resource scanout_templat = *template;
struct renderonly_scanout *scanout;
struct winsys_handle handle;
struct pipe_resource *res;
scanout = renderonly_scanout_for_resource(&scanout_templat,
- pscreen->ro, &handle);
+ dev->ro, &handle);
if (!scanout)
return NULL;
}
static void
-panfrost_resource_create_bo(struct panfrost_screen *screen, struct panfrost_resource *pres)
+panfrost_resource_create_bo(struct panfrost_device *dev, struct panfrost_resource *pres)
{
struct pipe_resource *res = &pres->base;
bool is_2d = (res->target == PIPE_TEXTURE_2D);
bool is_sane_bpp = bpp == 8 || bpp == 16 || bpp == 32 || bpp == 64 || bpp == 128;
bool should_tile = (res->usage != PIPE_USAGE_STREAM);
- bool must_tile = (res->bind & PIPE_BIND_DEPTH_STENCIL) && (screen->quirks & MIDGARD_SFBD);
+ bool must_tile = (res->bind & PIPE_BIND_DEPTH_STENCIL) && (dev->quirks & MIDGARD_SFBD);
bool can_tile = is_2d && is_sane_bpp && ((res->bind & ~valid_binding) == 0);
/* FBOs we would like to checksum, if at all possible */
/* We create a BO immediately but don't bother mapping, since we don't
* care to map e.g. FBOs which the CPU probably won't touch */
- pres->bo = panfrost_bo_create(screen, bo_size, PAN_BO_DELAY_MMAP);
+ pres->bo = panfrost_bo_create(dev, bo_size, PAN_BO_DELAY_MMAP);
}
void
return panfrost_create_scanout_res(screen, template);
struct panfrost_resource *so = rzalloc(screen, struct panfrost_resource);
- struct panfrost_screen *pscreen = (struct panfrost_screen *) screen;
+ struct panfrost_device *dev = pan_device(screen);
so->base = *template;
so->base.screen = screen;
util_range_init(&so->valid_buffer_range);
- panfrost_resource_create_bo(pscreen, so);
+ panfrost_resource_create_bo(dev, so);
panfrost_resource_reset_damage(so);
if (template->bind & PIPE_BIND_INDEX_BUFFER)
panfrost_resource_destroy(struct pipe_screen *screen,
struct pipe_resource *pt)
{
- struct panfrost_screen *pscreen = pan_screen(screen);
+ struct panfrost_device *dev = pan_device(screen);
struct panfrost_resource *rsrc = (struct panfrost_resource *) pt;
if (rsrc->scanout)
- renderonly_scanout_destroy(rsrc->scanout, pscreen->ro);
+ renderonly_scanout_destroy(rsrc->scanout, dev->ro);
if (rsrc->bo)
panfrost_bo_unreference(rsrc->bo);
*/
if (panfrost_pending_batches_access_bo(ctx, bo) ||
!panfrost_bo_wait(bo, 0, PAN_BO_ACCESS_RW)) {
- struct panfrost_screen *screen = pan_screen(pctx->screen);
+ struct panfrost_device *dev = pan_device(pctx->screen);
/* We want the BO to be MMAPed. */
uint32_t flags = bo->flags & ~PAN_BO_DELAY_MMAP;
struct panfrost_bo *newbo = NULL;
* doing to it.
*/
if (!(bo->flags & (PAN_BO_IMPORTED | PAN_BO_EXPORTED)))
- newbo = panfrost_bo_create(screen, bo->size,
+ newbo = panfrost_bo_create(dev, bo->size,
flags);
if (newbo) {
void
panfrost_resource_hint_layout(
- struct panfrost_screen *screen,
+ struct panfrost_device *dev,
struct panfrost_resource *rsrc,
enum mali_texture_layout layout,
signed weight)
/* If we grew in size, reallocate the BO */
if (new_size > rsrc->bo->size) {
panfrost_bo_unreference(rsrc->bo);
- rsrc->bo = panfrost_bo_create(screen, new_size, PAN_BO_DELAY_MMAP);
+ rsrc->bo = panfrost_bo_create(dev, new_size, PAN_BO_DELAY_MMAP);
}
/* TODO: If there are textures bound, regenerate their descriptors */
};
void
-panfrost_resource_screen_init(struct panfrost_screen *pscreen)
+panfrost_resource_screen_init(struct pipe_screen *pscreen)
{
//pscreen->base.resource_create_with_modifiers =
// panfrost_resource_create_with_modifiers;
- pscreen->base.resource_create = u_transfer_helper_resource_create;
- pscreen->base.resource_destroy = u_transfer_helper_resource_destroy;
- pscreen->base.resource_from_handle = panfrost_resource_from_handle;
- pscreen->base.resource_get_handle = panfrost_resource_get_handle;
- pscreen->base.transfer_helper = u_transfer_helper_create(&transfer_vtbl,
+ pscreen->resource_create = u_transfer_helper_resource_create;
+ pscreen->resource_destroy = u_transfer_helper_resource_destroy;
+ pscreen->resource_from_handle = panfrost_resource_from_handle;
+ pscreen->resource_get_handle = panfrost_resource_get_handle;
+ pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl,
true, false,
true, true);
}
struct panfrost_resource *rsrc,
unsigned level, unsigned face);
-void panfrost_resource_screen_init(struct panfrost_screen *screen);
+void panfrost_resource_screen_init(struct pipe_screen *screen);
void panfrost_resource_context_init(struct pipe_context *pctx);
void
panfrost_resource_hint_layout(
- struct panfrost_screen *screen,
+ struct panfrost_device *dev,
struct panfrost_resource *rsrc,
enum mali_texture_layout layout,
signed weight);
static const char *
panfrost_get_name(struct pipe_screen *screen)
{
- return panfrost_model_name(pan_screen(screen)->gpu_id);
+ return panfrost_model_name(pan_device(screen)->gpu_id);
}
static const char *
static void
panfrost_destroy_screen(struct pipe_screen *pscreen)
{
- struct panfrost_screen *screen = pan_screen(pscreen);
- panfrost_bo_cache_evict_all(screen);
- pthread_mutex_destroy(&screen->bo_cache.lock);
- pthread_mutex_destroy(&screen->active_bos_lock);
- drmFreeVersion(screen->kernel_version);
- ralloc_free(screen);
+ struct panfrost_device *dev = pan_device(pscreen);
+ panfrost_bo_cache_evict_all(dev);
+ pthread_mutex_destroy(&dev->bo_cache.lock);
+ pthread_mutex_destroy(&dev->active_bos_lock);
+ drmFreeVersion(dev->kernel_version);
+ ralloc_free(pscreen);
}
static uint64_t
struct pipe_fence_handle *fence,
uint64_t timeout)
{
- struct panfrost_screen *screen = pan_screen(pscreen);
+ struct panfrost_device *dev = pan_device(pscreen);
struct panfrost_fence *f = (struct panfrost_fence *)fence;
struct util_dynarray syncobjs;
int ret;
util_dynarray_foreach(&f->syncfds, int, fd) {
uint32_t syncobj;
- ret = drmSyncobjCreate(screen->fd, 0, &syncobj);
+ ret = drmSyncobjCreate(dev->fd, 0, &syncobj);
assert(!ret);
- ret = drmSyncobjImportSyncFile(screen->fd, syncobj, *fd);
+ ret = drmSyncobjImportSyncFile(dev->fd, syncobj, *fd);
assert(!ret);
util_dynarray_append(&syncobjs, uint32_t, syncobj);
}
if (abs_timeout == OS_TIMEOUT_INFINITE)
abs_timeout = INT64_MAX;
- ret = drmSyncobjWait(screen->fd, util_dynarray_begin(&syncobjs),
+ ret = drmSyncobjWait(dev->fd, util_dynarray_begin(&syncobjs),
util_dynarray_num_elements(&syncobjs, uint32_t),
abs_timeout, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL,
NULL);
util_dynarray_foreach(&syncobjs, uint32_t, syncobj)
- drmSyncobjDestroy(screen->fd, *syncobj);
+ drmSyncobjDestroy(dev->fd, *syncobj);
return ret >= 0;
}
panfrost_fence_create(struct panfrost_context *ctx,
struct util_dynarray *fences)
{
- struct panfrost_screen *screen = pan_screen(ctx->base.screen);
+ struct panfrost_device *device = pan_device(ctx->base.screen);
struct panfrost_fence *f = calloc(1, sizeof(*f));
if (!f)
return NULL;
if ((*fence)->signaled)
continue;
- drmSyncobjExportSyncFile(screen->fd, (*fence)->syncobj, &fd);
+ drmSyncobjExportSyncFile(device->fd, (*fence)->syncobj, &fd);
if (fd == -1)
fprintf(stderr, "export failed: %m\n");
if (!screen)
return NULL;
+ struct panfrost_device *dev = pan_device(&screen->base);
+
if (ro) {
- screen->ro = renderonly_dup(ro);
- if (!screen->ro) {
+ dev->ro = renderonly_dup(ro);
+ if (!dev->ro) {
DBG("Failed to dup renderonly object\n");
free(screen);
return NULL;
}
}
- screen->fd = fd;
+ dev->fd = fd;
+ dev->memctx = screen;
- screen->gpu_id = panfrost_query_gpu_version(screen->fd);
- screen->core_count = panfrost_query_core_count(screen->fd);
- screen->thread_tls_alloc = panfrost_query_thread_tls_alloc(screen->fd);
- screen->quirks = panfrost_get_quirks(screen->gpu_id);
- screen->kernel_version = drmGetVersion(fd);
+ dev->gpu_id = panfrost_query_gpu_version(dev->fd);
+ dev->core_count = panfrost_query_core_count(dev->fd);
+ dev->thread_tls_alloc = panfrost_query_thread_tls_alloc(dev->fd);
+ dev->quirks = panfrost_get_quirks(dev->gpu_id);
+ dev->kernel_version = drmGetVersion(fd);
/* Check if we're loading against a supported GPU model. */
- switch (screen->gpu_id) {
+ switch (dev->gpu_id) {
case 0x720: /* T720 */
case 0x750: /* T760 */
case 0x820: /* T820 */
break;
default:
/* Fail to load against untested models */
- debug_printf("panfrost: Unsupported model %X", screen->gpu_id);
+ debug_printf("panfrost: Unsupported model %X", dev->gpu_id);
return NULL;
}
- pthread_mutex_init(&screen->active_bos_lock, NULL);
- screen->active_bos = _mesa_set_create(screen, panfrost_active_bos_hash,
+ pthread_mutex_init(&dev->active_bos_lock, NULL);
+ dev->active_bos = _mesa_set_create(screen, panfrost_active_bos_hash,
panfrost_active_bos_cmp);
- pthread_mutex_init(&screen->bo_cache.lock, NULL);
- list_inithead(&screen->bo_cache.lru);
- for (unsigned i = 0; i < ARRAY_SIZE(screen->bo_cache.buckets); ++i)
- list_inithead(&screen->bo_cache.buckets[i]);
+ pthread_mutex_init(&dev->bo_cache.lock, NULL);
+ list_inithead(&dev->bo_cache.lru);
+ for (unsigned i = 0; i < ARRAY_SIZE(dev->bo_cache.buckets); ++i)
+ list_inithead(&dev->bo_cache.buckets[i]);
if (pan_debug & (PAN_DBG_TRACE | PAN_DBG_SYNC))
pandecode_initialize(!(pan_debug & PAN_DBG_TRACE));
screen->base.fence_finish = panfrost_fence_finish;
screen->base.set_damage_region = panfrost_resource_set_damage_region;
- panfrost_resource_screen_init(screen);
+ panfrost_resource_screen_init(&screen->base);
return &screen->base;
}
#include "util/set.h"
#include <panfrost-misc.h>
+#include "pan_device.h"
#include "pan_allocate.h"
struct panfrost_batch;
struct panfrost_context;
struct panfrost_resource;
-struct panfrost_screen;
-
-/* Driver limits */
-#define PAN_MAX_CONST_BUFFERS 16
-
-/* Transient slab size. This is a balance between fragmentation against cache
- * locality and ease of bookkeeping */
-
-#define TRANSIENT_SLAB_PAGES (32) /* 128kb */
-#define TRANSIENT_SLAB_SIZE (4096 * TRANSIENT_SLAB_PAGES)
-
-/* Maximum number of transient slabs so we don't need dynamic arrays. Most
- * interesting Mali boards are 4GB RAM max, so if the entire RAM was filled
- * with transient slabs, you could never exceed (4GB / TRANSIENT_SLAB_SIZE)
- * allocations anyway. By capping, we can use a fixed-size bitset for tracking
- * free slabs, eliminating quite a bit of complexity. We can pack the free
- * state of 8 slabs into a single byte, so for 128kb transient slabs the bitset
- * occupies a cheap 4kb of memory */
-
-#define MAX_TRANSIENT_SLABS (1024*1024 / TRANSIENT_SLAB_PAGES)
-
-/* How many power-of-two levels in the BO cache do we want? 2^12
- * minimum chosen as it is the page size that all allocations are
- * rounded to */
-
-#define MIN_BO_CACHE_BUCKET (12) /* 2^12 = 4KB */
-#define MAX_BO_CACHE_BUCKET (22) /* 2^22 = 4MB */
-
-/* Fencepost problem, hence the off-by-one */
-#define NR_BO_CACHE_BUCKETS (MAX_BO_CACHE_BUCKET - MIN_BO_CACHE_BUCKET + 1)
struct panfrost_screen {
struct pipe_screen base;
- int fd;
-
- /* Properties of the GPU in use */
- unsigned gpu_id;
- unsigned core_count;
- unsigned thread_tls_alloc;
- unsigned quirks;
-
- drmVersionPtr kernel_version;
-
- struct renderonly *ro;
-
- pthread_mutex_t active_bos_lock;
- struct set *active_bos;
-
- struct {
- pthread_mutex_t lock;
-
- /* List containing all cached BOs sorted in LRU (Least
- * Recently Used) order. This allows us to quickly evict BOs
- * that are more than 1 second old.
- */
- struct list_head lru;
-
- /* The BO cache is a set of buckets with power-of-two sizes
- * ranging from 2^12 (4096, the page size) to
- * 2^(12 + MAX_BO_CACHE_BUCKETS).
- * Each bucket is a linked list of free panfrost_bo objects. */
-
- struct list_head buckets[NR_BO_CACHE_BUCKETS];
- } bo_cache;
+ struct panfrost_device dev;
};
static inline struct panfrost_screen *
return (struct panfrost_screen *)p;
}
+static inline struct panfrost_device *
+pan_device(struct pipe_screen *p)
+{
+ return &(pan_screen(p)->dev);
+}
+
struct panfrost_fence *
panfrost_fence_create(struct panfrost_context *ctx,
struct util_dynarray *fences);
{
struct panfrost_context *ctx = batch->ctx;
struct pipe_context *gallium = (struct pipe_context *) ctx;
- struct panfrost_screen *screen = pan_screen(gallium->screen);
+ struct panfrost_device *dev = pan_device(gallium->screen);
unsigned width = batch->key.width;
unsigned height = batch->key.height;
.height = MALI_POSITIVE(height),
.shared_memory = {
.shared_workgroup_count = ~0,
- .scratchpad = panfrost_batch_get_scratchpad(batch, shift, screen->thread_tls_alloc, screen->core_count)->gpu,
+ .scratchpad = panfrost_batch_get_scratchpad(batch, shift, dev->thread_tls_alloc, dev->core_count)->gpu,
},
.format = {
.unk3 = 0x3,
encoder_FILES := \
encoder/pan_afbc.c \
encoder/pan_attributes.c \
+ encoder/pan_device.h \
encoder/pan_encoder.h \
encoder/pan_format.c \
encoder/pan_invocation.c \
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2018-2019 Alyssa Rosenzweig
+ * Copyright 2018-2019 Collabora, Ltd.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef PAN_DEVICE_H
+#define PAN_DEVICE_H
+
+#include <xf86drm.h>
+#include "renderonly/renderonly.h"
+#include "util/u_dynarray.h"
+#include "util/bitset.h"
+#include "util/set.h"
+
+#include <panfrost-misc.h>
+#include "pan_allocate.h"
+
+/* Driver limits */
+#define PAN_MAX_CONST_BUFFERS 16
+
+/* Transient slab size. This is a balance between fragmentation against cache
+ * locality and ease of bookkeeping */
+
+#define TRANSIENT_SLAB_PAGES (32) /* 128kb */
+#define TRANSIENT_SLAB_SIZE (4096 * TRANSIENT_SLAB_PAGES)
+
+/* Maximum number of transient slabs so we don't need dynamic arrays. Most
+ * interesting Mali boards are 4GB RAM max, so if the entire RAM was filled
+ * with transient slabs, you could never exceed (4GB / TRANSIENT_SLAB_SIZE)
+ * allocations anyway. By capping, we can use a fixed-size bitset for tracking
+ * free slabs, eliminating quite a bit of complexity. We can pack the free
+ * state of 8 slabs into a single byte, so for 128kb transient slabs the bitset
+ * occupies a cheap 4kb of memory */
+
+#define MAX_TRANSIENT_SLABS (1024*1024 / TRANSIENT_SLAB_PAGES)
+
+/* How many power-of-two levels in the BO cache do we want? 2^12
+ * minimum chosen as it is the page size that all allocations are
+ * rounded to */
+
+#define MIN_BO_CACHE_BUCKET (12) /* 2^12 = 4KB */
+#define MAX_BO_CACHE_BUCKET (22) /* 2^22 = 4MB */
+
+/* Fencepost problem, hence the off-by-one */
+#define NR_BO_CACHE_BUCKETS (MAX_BO_CACHE_BUCKET - MIN_BO_CACHE_BUCKET + 1)
+
+struct panfrost_device {
+ /* For ralloc */
+ void *memctx;
+
+ int fd;
+
+ /* Properties of the GPU in use */
+ unsigned gpu_id;
+ unsigned core_count;
+ unsigned thread_tls_alloc;
+ unsigned quirks;
+
+ drmVersionPtr kernel_version;
+
+ struct renderonly *ro;
+
+ pthread_mutex_t active_bos_lock;
+ struct set *active_bos;
+
+ struct {
+ pthread_mutex_t lock;
+
+ /* List containing all cached BOs sorted in LRU (Least
+ * Recently Used) order. This allows us to quickly evict BOs
+ * that are more than 1 second old.
+ */
+ struct list_head lru;
+
+ /* The BO cache is a set of buckets with power-of-two sizes
+ * ranging from 2^12 (4096, the page size) to
+ * 2^(12 + MAX_BO_CACHE_BUCKETS).
+ * Each bucket is a linked list of free panfrost_bo objects. */
+
+ struct list_head buckets[NR_BO_CACHE_BUCKETS];
+ } bo_cache;
+};
+
+#endif