vc4: Initial skeleton driver import.
This mostly just takes every draw call and turns it into a sequence of commands that clear the FBO and draw a single shaded triangle to it, regardless of the actual input vertices or shaders. I copied the initial driver skeleton mostly from freedreno, and I've preserved Rob Clark's copyright for those. I also based my initial hardcoded shaders and command lists on Scott Mansell (phire)'s "hackdriver" project, though the bit patterns of the shaders emitted end up being different. v2: Rebase on gallium megadrivers changes. v3: Rebase on PIPE_SHADER_CAP_MAX_CONSTS change. v4: Rely on simpenrose actually being installed when building for simulation. v5: Add more header duplicate-include guards. v6: Apply Emil's review (protection against vc4 sim and ilo at the same time, and dropping the dricommon drm bits) and fix a copyright header (thanks, Roland)
This commit is contained in:
parent
f017e32c0a
commit
1850d0a1cb
21
configure.ac
21
configure.ac
|
@ -723,7 +723,7 @@ GALLIUM_DRIVERS_DEFAULT="r300,r600,svga,swrast"
|
|||
AC_ARG_WITH([gallium-drivers],
|
||||
[AS_HELP_STRING([--with-gallium-drivers@<:@=DIRS...@:>@],
|
||||
[comma delimited Gallium drivers list, e.g.
|
||||
"i915,ilo,nouveau,r300,r600,radeonsi,freedreno,svga,swrast"
|
||||
"i915,ilo,nouveau,r300,r600,radeonsi,freedreno,svga,swrast,vc4"
|
||||
@<:@default=r300,r600,svga,swrast@:>@])],
|
||||
[with_gallium_drivers="$withval"],
|
||||
[with_gallium_drivers="$GALLIUM_DRIVERS_DEFAULT"])
|
||||
|
@ -2002,6 +2002,18 @@ if test -n "$with_gallium_drivers"; then
|
|||
GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS dri/kms-swrast"
|
||||
fi
|
||||
;;
|
||||
xvc4)
|
||||
HAVE_GALLIUM_VC4=yes
|
||||
gallium_require_drm_loader
|
||||
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS vc4"
|
||||
gallium_check_st "vc4/drm" "dri-vc4" "" "" ""
|
||||
|
||||
case "$host_cpu" in
|
||||
i?86 | x86_64 | amd64)
|
||||
USE_VC4_SIMULATOR=yes
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([Unknown Gallium driver: $driver])
|
||||
;;
|
||||
|
@ -2063,6 +2075,7 @@ AM_CONDITIONAL(HAVE_GALLIUM_NOUVEAU, test "x$HAVE_GALLIUM_NOUVEAU" = xyes)
|
|||
AM_CONDITIONAL(HAVE_GALLIUM_FREEDRENO, test "x$HAVE_GALLIUM_FREEDRENO" = xyes)
|
||||
AM_CONDITIONAL(HAVE_GALLIUM_SOFTPIPE, test "x$HAVE_GALLIUM_SOFTPIPE" = xyes)
|
||||
AM_CONDITIONAL(HAVE_GALLIUM_LLVMPIPE, test "x$HAVE_GALLIUM_LLVMPIPE" = xyes)
|
||||
AM_CONDITIONAL(HAVE_GALLIUM_VC4, test "x$HAVE_GALLIUM_VC4" = xyes)
|
||||
|
||||
AM_CONDITIONAL(NEED_GALLIUM_SOFTPIPE_DRIVER, test "x$HAVE_GALLIUM_SVGA" = xyes -o \
|
||||
"x$HAVE_GALLIUM_SOFTPIPE" = xyes)
|
||||
|
@ -2128,6 +2141,10 @@ AM_CONDITIONAL(HAVE_LOADER_GALLIUM, test x$enable_gallium_loader = xyes)
|
|||
AM_CONDITIONAL(HAVE_DRM_LOADER_GALLIUM, test x$enable_gallium_drm_loader = xyes)
|
||||
AM_CONDITIONAL(HAVE_GALLIUM_COMPUTE, test x$enable_opencl = xyes)
|
||||
AM_CONDITIONAL(HAVE_MESA_LLVM, test x$MESA_LLVM = x1)
|
||||
AM_CONDITIONAL(USE_VC4_SIMULATOR, test x$USE_VC4_SIMULATOR = xyes)
|
||||
if test "x$USE_VC4_SIMULATOR" = xyes -a "x$HAVE_GALLIUM_ILO" = xyes; then
|
||||
AC_MSG_ERROR([VC4 simulator on x86 replaces i965 driver build, so ilo must be disabled.])
|
||||
fi
|
||||
|
||||
AC_SUBST([ELF_LIB])
|
||||
|
||||
|
@ -2200,6 +2217,7 @@ AC_CONFIG_FILES([Makefile
|
|||
src/gallium/drivers/softpipe/Makefile
|
||||
src/gallium/drivers/svga/Makefile
|
||||
src/gallium/drivers/trace/Makefile
|
||||
src/gallium/drivers/vc4/Makefile
|
||||
src/gallium/state_trackers/Makefile
|
||||
src/gallium/state_trackers/clover/Makefile
|
||||
src/gallium/state_trackers/dri/Makefile
|
||||
|
@ -2242,6 +2260,7 @@ AC_CONFIG_FILES([Makefile
|
|||
src/gallium/winsys/sw/wayland/Makefile
|
||||
src/gallium/winsys/sw/wrapper/Makefile
|
||||
src/gallium/winsys/sw/xlib/Makefile
|
||||
src/gallium/winsys/vc4/drm/Makefile
|
||||
src/gbm/Makefile
|
||||
src/gbm/main/gbm.pc
|
||||
src/glsl/Makefile
|
||||
|
|
|
@ -54,6 +54,10 @@
|
|||
#include "freedreno/drm/freedreno_drm_public.h"
|
||||
#endif
|
||||
|
||||
#if GALLIUM_VC4
|
||||
#include "vc4/drm/vc4_drm_public.h"
|
||||
#endif
|
||||
|
||||
static char* driver_name = NULL;
|
||||
|
||||
/* XXX: We need to teardown the winsys if *screen_create() fails. */
|
||||
|
@ -286,6 +290,48 @@ pipe_freedreno_create_screen(int fd)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(GALLIUM_VC4)
|
||||
#if defined(DRI_TARGET)
|
||||
|
||||
const __DRIextension **__driDriverGetExtensions_vc4(void);
|
||||
|
||||
PUBLIC const __DRIextension **__driDriverGetExtensions_vc4(void)
|
||||
{
|
||||
globalDriverAPI = &galliumdrm_driver_api;
|
||||
return galliumdrm_driver_extensions;
|
||||
}
|
||||
|
||||
#if defined(USE_VC4_SIMULATOR)
|
||||
const __DRIextension **__driDriverGetExtensions_i965(void);
|
||||
|
||||
/**
|
||||
* When building using the simulator (on x86), we advertise ourselves as the
|
||||
* i965 driver so that you can just make a directory with a link from
|
||||
* i965_dri.so to the built vc4_dri.so, and point LIBGL_DRIVERS_PATH to that
|
||||
* on your i965-using host to run the driver under simulation.
|
||||
*
|
||||
* This is, of course, incompatible with building with the ilo driver, but you
|
||||
* shouldn't be building that anyway.
|
||||
*/
|
||||
PUBLIC const __DRIextension **__driDriverGetExtensions_i965(void)
|
||||
{
|
||||
globalDriverAPI = &galliumdrm_driver_api;
|
||||
return galliumdrm_driver_extensions;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static struct pipe_screen *
|
||||
pipe_vc4_create_screen(int fd)
|
||||
{
|
||||
struct pipe_screen *screen;
|
||||
|
||||
screen = vc4_drm_screen_create(fd);
|
||||
return screen ? debug_screen_wrap(screen) : NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline struct pipe_screen *
|
||||
dd_create_screen(int fd)
|
||||
{
|
||||
|
@ -332,6 +378,16 @@ dd_create_screen(int fd)
|
|||
if ((strcmp(driver_name, "kgsl") == 0) || (strcmp(driver_name, "msm") == 0))
|
||||
return pipe_freedreno_create_screen(fd);
|
||||
else
|
||||
#endif
|
||||
#if defined(GALLIUM_VC4)
|
||||
if (strcmp(driver_name, "vc4") == 0)
|
||||
return pipe_vc4_create_screen(fd);
|
||||
else
|
||||
#if defined(USE_VC4_SIMULATOR)
|
||||
if (strcmp(driver_name, "i965") == 0)
|
||||
return pipe_vc4_create_screen(fd);
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -90,3 +90,11 @@ if NEED_GALLIUM_LLVMPIPE_DRIVER
|
|||
SUBDIRS += llvmpipe
|
||||
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
||||
if HAVE_GALLIUM_VC4
|
||||
|
||||
SUBDIRS += vc4
|
||||
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
((nil
|
||||
(indent-tabs-mode . nil)
|
||||
(tab-width . 8)
|
||||
(c-basic-offset . 8)
|
||||
(c-file-style . "stroustrup")
|
||||
(fill-column . 78)
|
||||
(eval . (progn
|
||||
(c-set-offset 'innamespace '0)
|
||||
(c-set-offset 'inline-open '0)))
|
||||
)
|
||||
(makefile-mode (indent-tabs-mode . t))
|
||||
)
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright © 2014 Broadcom
|
||||
#
|
||||
# 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 Makefile.sources
|
||||
include $(top_srcdir)/src/gallium/Automake.inc
|
||||
|
||||
if USE_VC4_SIMULATOR
|
||||
SIM_CFLAGS = -DUSE_VC4_SIMULATOR=1
|
||||
SIM_LDFLAGS = -lsimpenrose
|
||||
endif
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(LIBDRM_CFLAGS) \
|
||||
$(GALLIUM_DRIVER_CFLAGS) \
|
||||
$(SIM_CFLAGS) \
|
||||
$()
|
||||
|
||||
noinst_LTLIBRARIES = libvc4.la
|
||||
|
||||
libvc4_la_SOURCES = $(C_SOURCES)
|
||||
libvc4_la_LIBADD = $(SIM_LIB)
|
||||
libvc4_la_LDFLAGS = $(SIM_LDFLAGS)
|
|
@ -0,0 +1,15 @@
|
|||
C_SOURCES := \
|
||||
vc4_bufmgr.c \
|
||||
vc4_cl.c \
|
||||
vc4_context.c \
|
||||
vc4_draw.c \
|
||||
vc4_emit.c \
|
||||
vc4_program.c \
|
||||
vc4_qpu.c \
|
||||
vc4_qpu_disasm.c \
|
||||
vc4_qpu_validate.c \
|
||||
vc4_resource.c \
|
||||
vc4_screen.c \
|
||||
vc4_simulator.c \
|
||||
vc4_state.c \
|
||||
$()
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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 <err.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "vc4_context.h"
|
||||
#include "vc4_screen.h"
|
||||
|
||||
struct vc4_bo *
|
||||
vc4_bo_alloc(struct vc4_screen *screen, uint32_t size, const char *name)
|
||||
{
|
||||
struct vc4_bo *bo = CALLOC_STRUCT(vc4_bo);
|
||||
if (!bo)
|
||||
return NULL;
|
||||
|
||||
pipe_reference_init(&bo->reference, 1);
|
||||
bo->screen = screen;
|
||||
bo->size = size;
|
||||
bo->name = name;
|
||||
|
||||
#ifndef USE_VC4_SIMULATOR
|
||||
struct drm_mode_create_dumb create;
|
||||
memset(&create, 0, sizeof(create));
|
||||
|
||||
create.width = 128;
|
||||
create.bpp = 8;
|
||||
create.height = (size + 127) / 128;
|
||||
|
||||
int ret = drmIoctl(screen->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
|
||||
if (ret != 0)
|
||||
errx(1, "create ioctl");
|
||||
|
||||
bo->handle = create.handle;
|
||||
assert(create.size >= size);
|
||||
#else /* USE_VC4_SIMULATOR */
|
||||
bo->map = vc4_simulator_alloc(screen, size);
|
||||
#endif /* USE_VC4_SIMULATOR */
|
||||
|
||||
return bo;
|
||||
}
|
||||
|
||||
void
|
||||
vc4_bo_free(struct vc4_bo *bo)
|
||||
{
|
||||
#ifndef USE_VC4_SIMULATOR
|
||||
struct vc4_screen *screen = bo->screen;
|
||||
|
||||
struct drm_gem_close c;
|
||||
c.handle = bo->handle;
|
||||
int ret = drmIoctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &c);
|
||||
if (ret != 0)
|
||||
fprintf(stderr, "close object %d: %s\n", bo->handle, strerror(errno));
|
||||
#endif
|
||||
|
||||
free(bo);
|
||||
}
|
||||
|
||||
struct vc4_bo *
|
||||
vc4_bo_open_name(struct vc4_screen *screen, uint32_t name,
|
||||
uint32_t winsys_stride)
|
||||
{
|
||||
struct vc4_bo *bo = CALLOC_STRUCT(vc4_bo);
|
||||
|
||||
struct drm_gem_open o;
|
||||
o.name = name;
|
||||
int ret = drmIoctl(screen->fd, DRM_IOCTL_GEM_OPEN, &o);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Failed to open bo %d: %s\n",
|
||||
name, strerror(errno));
|
||||
free(bo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pipe_reference_init(&bo->reference, 1);
|
||||
bo->screen = screen;
|
||||
bo->handle = o.handle;
|
||||
bo->size = o.size;
|
||||
|
||||
#ifdef USE_VC4_SIMULATOR
|
||||
vc4_bo_map(bo);
|
||||
bo->simulator_winsys_map = bo->map;
|
||||
bo->simulator_winsys_stride = winsys_stride;
|
||||
bo->map = vc4_simulator_alloc(screen, bo->size);
|
||||
#endif
|
||||
|
||||
return bo;
|
||||
}
|
||||
|
||||
struct vc4_bo *
|
||||
vc4_bo_alloc_mem(struct vc4_screen *screen, const void *data, uint32_t size,
|
||||
const char *name)
|
||||
{
|
||||
void *map;
|
||||
struct vc4_bo *bo;
|
||||
|
||||
bo = vc4_bo_alloc(screen, size, name);
|
||||
map = vc4_bo_map(bo);
|
||||
memcpy(map, data, size);
|
||||
return bo;
|
||||
}
|
||||
|
||||
bool
|
||||
vc4_bo_flink(struct vc4_bo *bo, uint32_t *name)
|
||||
{
|
||||
#ifndef USE_VC4_SIMULATOR
|
||||
struct drm_gem_flink flink = {
|
||||
.handle = bo->handle,
|
||||
};
|
||||
int ret = drmIoctl(bo->screen->fd, DRM_IOCTL_GEM_FLINK, &flink);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Failed to flink bo %d: %s\n",
|
||||
bo->handle, strerror(errno));
|
||||
free(bo);
|
||||
return false;
|
||||
}
|
||||
|
||||
*name = flink.name;
|
||||
#endif /* USE_VC4_SIMULATOR */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void *
|
||||
vc4_bo_map(struct vc4_bo *bo)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (bo->map)
|
||||
return bo->map;
|
||||
|
||||
struct drm_mode_map_dumb map;
|
||||
memset(&map, 0, sizeof(map));
|
||||
map.handle = bo->handle;
|
||||
ret = drmIoctl(bo->screen->fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
|
||||
if (ret != 0)
|
||||
errx(1, "map ioctl");
|
||||
|
||||
bo->map = mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
bo->screen->fd, map.offset);
|
||||
if (bo->map == MAP_FAILED) {
|
||||
errx(1, "mmap of bo %d (offset 0x%016llx, size %d) failed\n",
|
||||
bo->handle, (long long)map.offset, bo->size);
|
||||
}
|
||||
|
||||
return bo->map;
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef VC4_BUFMGR_H
|
||||
#define VC4_BUFMGR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "util/u_inlines.h"
|
||||
|
||||
struct vc4_context;
|
||||
|
||||
struct vc4_bo {
|
||||
struct pipe_reference reference;
|
||||
struct vc4_screen *screen;
|
||||
void *map;
|
||||
const char *name;
|
||||
uint32_t handle;
|
||||
uint32_t size;
|
||||
|
||||
#ifdef USE_VC4_SIMULATOR
|
||||
void *simulator_winsys_map;
|
||||
uint32_t simulator_winsys_stride;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct vc4_bo *vc4_bo_alloc(struct vc4_screen *screen, uint32_t size,
|
||||
const char *name);
|
||||
struct vc4_bo *vc4_bo_alloc_mem(struct vc4_screen *screen, const void *data,
|
||||
uint32_t size, const char *name);
|
||||
void vc4_bo_free(struct vc4_bo *bo);
|
||||
struct vc4_bo *vc4_bo_open_name(struct vc4_screen *screen, uint32_t name,
|
||||
uint32_t winsys_stride);
|
||||
bool vc4_bo_flink(struct vc4_bo *bo, uint32_t *name);
|
||||
|
||||
static inline void
|
||||
vc4_bo_set_reference(struct vc4_bo **old_bo, struct vc4_bo *new_bo)
|
||||
{
|
||||
if (pipe_reference(&(*old_bo)->reference, &new_bo->reference))
|
||||
vc4_bo_free(*old_bo);
|
||||
*old_bo = new_bo;
|
||||
}
|
||||
|
||||
static inline struct vc4_bo *
|
||||
vc4_bo_reference(struct vc4_bo *bo)
|
||||
{
|
||||
pipe_reference(NULL, &bo->reference);
|
||||
return bo;
|
||||
}
|
||||
|
||||
static inline void
|
||||
vc4_bo_unreference(struct vc4_bo **bo)
|
||||
{
|
||||
if (pipe_reference(&(*bo)->reference, NULL))
|
||||
vc4_bo_free(*bo);
|
||||
*bo = NULL;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
vc4_bo_map(struct vc4_bo *bo);
|
||||
|
||||
#endif /* VC4_BUFMGR_H */
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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 "util/u_math.h"
|
||||
#include "vc4_context.h"
|
||||
|
||||
void
|
||||
vc4_init_cl(struct vc4_context *vc4, struct vc4_cl *cl)
|
||||
{
|
||||
#ifdef USE_VC4_SIMULATOR
|
||||
uint32_t size = 256 * 1024;
|
||||
cl->base = vc4_simulator_alloc(vc4->screen, size);
|
||||
cl->end = cl->base + size;
|
||||
cl->next = cl->base;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
vc4_grow_cl(struct vc4_cl *cl)
|
||||
{
|
||||
uint32_t size = MAX2((cl->end - cl->base) * 2, 4096);
|
||||
uint32_t offset = cl->next -cl->base;
|
||||
|
||||
#ifdef USE_VC4_SIMULATOR
|
||||
assert(!"not reached");
|
||||
#endif
|
||||
cl->base = realloc(cl->base, size);
|
||||
cl->end = cl->base + size;
|
||||
cl->next = cl->base + offset;
|
||||
}
|
||||
|
||||
void
|
||||
vc4_reset_cl(struct vc4_cl *cl)
|
||||
{
|
||||
assert(cl->reloc_count == 0);
|
||||
cl->next = cl->base;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
vc4_gem_hindex(struct vc4_context *vc4, struct vc4_bo *bo)
|
||||
{
|
||||
uint32_t hindex;
|
||||
uint32_t *current_handles = vc4->bo_handles.base;
|
||||
|
||||
for (hindex = 0;
|
||||
hindex < (vc4->bo_handles.next - vc4->bo_handles.base) / 4;
|
||||
hindex++) {
|
||||
if (current_handles[hindex] == bo->handle)
|
||||
return hindex;
|
||||
}
|
||||
|
||||
cl_u32(&vc4->bo_handles, bo->handle);
|
||||
return hindex;
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef VC4_CL_H
|
||||
#define VC4_CL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
#ifdef USE_VC4_SIMULATOR
|
||||
#include "simpenrose/simpenrose.h"
|
||||
#endif
|
||||
|
||||
#include "vc4_packet.h"
|
||||
|
||||
struct vc4_bo;
|
||||
|
||||
struct vc4_cl {
|
||||
void *base;
|
||||
void *next;
|
||||
void *end;
|
||||
uint32_t reloc_next;
|
||||
uint32_t reloc_count;
|
||||
};
|
||||
|
||||
void vc4_init_cl(struct vc4_context *vc4, struct vc4_cl *cl);
|
||||
void vc4_grow_cl(struct vc4_cl *cl);
|
||||
void vc4_reset_cl(struct vc4_cl *cl);
|
||||
uint32_t vc4_gem_hindex(struct vc4_context *vc4, struct vc4_bo *bo);
|
||||
|
||||
static inline void
|
||||
cl_u8(struct vc4_cl *cl, uint8_t n)
|
||||
{
|
||||
if (cl->next + 1 > cl->end)
|
||||
vc4_grow_cl(cl);
|
||||
|
||||
*(uint8_t *)cl->next = n;
|
||||
cl->next++;
|
||||
}
|
||||
|
||||
static inline void
|
||||
cl_u16(struct vc4_cl *cl, uint32_t n)
|
||||
{
|
||||
if (cl->next + 2 > cl->end)
|
||||
vc4_grow_cl(cl);
|
||||
|
||||
*(uint16_t *)cl->next = n;
|
||||
cl->next += 2;
|
||||
}
|
||||
|
||||
static inline void
|
||||
cl_u32(struct vc4_cl *cl, uint32_t n)
|
||||
{
|
||||
if (cl->next + 4 > cl->end)
|
||||
vc4_grow_cl(cl);
|
||||
|
||||
*(uint32_t *)cl->next = n;
|
||||
cl->next += 4;
|
||||
}
|
||||
|
||||
static inline void
|
||||
cl_f(struct vc4_cl *cl, float f)
|
||||
{
|
||||
cl_u32(cl, fui(f));
|
||||
}
|
||||
|
||||
static inline void
|
||||
cl_start_reloc(struct vc4_cl *cl, uint32_t n)
|
||||
{
|
||||
assert(n == 1 || n == 2);
|
||||
assert(cl->reloc_count == 0);
|
||||
cl->reloc_count = n;
|
||||
|
||||
#ifndef USE_VC4_SIMULATOR
|
||||
cl_u8(cl, GEM_HANDLES);
|
||||
cl->reloc_next = cl->next - cl->base;
|
||||
cl_u32(cl, 0); /* Space where hindex will be written. */
|
||||
cl_u32(cl, 0); /* Space where hindex will be written. */
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
cl_start_shader_reloc(struct vc4_cl *cl, uint32_t n)
|
||||
{
|
||||
assert(cl->reloc_count == 0);
|
||||
cl->reloc_count = n;
|
||||
cl->reloc_next = cl->next - cl->base;
|
||||
|
||||
#ifndef USE_VC4_SIMULATOR
|
||||
for (int i = 0; i < n; i++)
|
||||
cl_u32(cl, 0); /* Space where hindex will be written. */
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
cl_reloc(struct vc4_context *vc4, struct vc4_cl *cl,
|
||||
struct vc4_bo *bo, uint32_t offset)
|
||||
{
|
||||
#ifndef USE_VC4_SIMULATOR
|
||||
*(uint32_t *)(cl->base + cl->reloc_next) = vc4_gem_hindex(vc4, bo);
|
||||
cl->reloc_next += 4;
|
||||
#else
|
||||
offset += simpenrose_hw_addr(bo->map);
|
||||
#endif
|
||||
|
||||
cl->reloc_count--;
|
||||
|
||||
cl_u32(cl, offset);
|
||||
}
|
||||
|
||||
#endif /* VC4_CL_H */
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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 <xf86drm.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_blitter.h"
|
||||
#include "pipe/p_screen.h"
|
||||
|
||||
#define __user
|
||||
#include "vc4_drm.h"
|
||||
#include "vc4_screen.h"
|
||||
#include "vc4_context.h"
|
||||
#include "vc4_resource.h"
|
||||
|
||||
static void
|
||||
dump_fbo(struct vc4_context *vc4, struct vc4_bo *fbo)
|
||||
{
|
||||
#ifndef USE_VC4_SIMULATOR
|
||||
uint32_t *map = vc4_bo_map(fbo);
|
||||
uint32_t width = vc4->framebuffer.width;
|
||||
uint32_t height = vc4->framebuffer.height;
|
||||
uint32_t chunk_w = width / 79;
|
||||
uint32_t chunk_h = height / 40;
|
||||
uint32_t found_colors[10];
|
||||
uint32_t num_found_colors = 0;
|
||||
|
||||
for (int by = 0; by < height; by += chunk_h) {
|
||||
for (int bx = 0; bx < width; bx += chunk_w) {
|
||||
bool on = false, black = false;
|
||||
|
||||
for (int y = by; y < MIN2(height, by + chunk_h); y++) {
|
||||
for (int x = bx; x < MIN2(width, bx + chunk_w); x++) {
|
||||
uint32_t pix = map[y * width + x];
|
||||
on |= pix != 0;
|
||||
black |= pix == 0xff000000;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < num_found_colors; i++) {
|
||||
if (pix == found_colors[i])
|
||||
break;
|
||||
}
|
||||
if (i == num_found_colors &&
|
||||
num_found_colors < Elements(found_colors))
|
||||
found_colors[num_found_colors++] = pix;
|
||||
}
|
||||
}
|
||||
if (black)
|
||||
fprintf(stderr, "O");
|
||||
else if (on)
|
||||
fprintf(stderr, "X");
|
||||
else
|
||||
fprintf(stderr, ".");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_found_colors; i++) {
|
||||
fprintf(stderr, "color %d: 0x%08x\n", i, found_colors[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
vc4_flush(struct pipe_context *pctx)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
|
||||
if (!vc4->needs_flush)
|
||||
return;
|
||||
|
||||
struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]);
|
||||
struct vc4_resource *ctex = vc4_resource(csurf->base.texture);
|
||||
struct drm_vc4_submit_cl submit;
|
||||
memset(&submit, 0, sizeof(submit));
|
||||
|
||||
submit.bo_handles = vc4->bo_handles.base;
|
||||
submit.bo_handle_count = (vc4->bo_handles.next -
|
||||
vc4->bo_handles.base) / 4;
|
||||
submit.bin_cl = vc4->bcl.base;
|
||||
submit.bin_cl_len = vc4->bcl.next - vc4->bcl.base;
|
||||
submit.render_cl = vc4->rcl.base;
|
||||
submit.render_cl_len = vc4->rcl.next - vc4->rcl.base;
|
||||
submit.shader_records = vc4->shader_rec.base;
|
||||
submit.shader_record_len = vc4->shader_rec.next - vc4->shader_rec.base;
|
||||
submit.shader_record_count = vc4->shader_rec_count;
|
||||
|
||||
#ifndef USE_VC4_SIMULATOR
|
||||
int ret = drmIoctl(vc4->fd, DRM_IOCTL_VC4_SUBMIT_CL, &submit);
|
||||
if (ret)
|
||||
errx(1, "VC4 submit failed\n");
|
||||
#else
|
||||
vc4_simulator_flush(vc4, csurf);
|
||||
#endif
|
||||
vc4_reset_cl(&vc4->bcl);
|
||||
vc4_reset_cl(&vc4->rcl);
|
||||
vc4_reset_cl(&vc4->shader_rec);
|
||||
vc4_reset_cl(&vc4->bo_handles);
|
||||
vc4->shader_rec_count = 0;
|
||||
|
||||
vc4->needs_flush = false;
|
||||
vc4->dirty = ~0;
|
||||
|
||||
dump_fbo(vc4, ctex->bo);
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_pipe_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
|
||||
unsigned flags)
|
||||
{
|
||||
vc4_flush(pctx);
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_context_destroy(struct pipe_context *pctx)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
|
||||
if (vc4->blitter)
|
||||
util_blitter_destroy(vc4->blitter);
|
||||
util_slab_destroy(&vc4->transfer_pool);
|
||||
|
||||
free(vc4);
|
||||
}
|
||||
|
||||
struct pipe_context *
|
||||
vc4_context_create(struct pipe_screen *pscreen, void *priv)
|
||||
{
|
||||
struct vc4_screen *screen = vc4_screen(pscreen);
|
||||
struct vc4_context *vc4;
|
||||
|
||||
vc4 = CALLOC_STRUCT(vc4_context);
|
||||
if (vc4 == NULL)
|
||||
return NULL;
|
||||
struct pipe_context *pctx = &vc4->base;
|
||||
|
||||
vc4->screen = screen;
|
||||
|
||||
pctx->screen = pscreen;
|
||||
pctx->priv = priv;
|
||||
pctx->destroy = vc4_context_destroy;
|
||||
pctx->flush = vc4_pipe_flush;
|
||||
|
||||
vc4_draw_init(pctx);
|
||||
vc4_state_init(pctx);
|
||||
vc4_program_init(pctx);
|
||||
vc4_resource_context_init(pctx);
|
||||
|
||||
vc4_init_cl(vc4, &vc4->bcl);
|
||||
vc4_init_cl(vc4, &vc4->rcl);
|
||||
vc4_init_cl(vc4, &vc4->shader_rec);
|
||||
vc4_init_cl(vc4, &vc4->bo_handles);
|
||||
|
||||
vc4->dirty = ~0;
|
||||
vc4->fd = screen->fd;
|
||||
|
||||
util_slab_create(&vc4->transfer_pool, sizeof(struct pipe_transfer),
|
||||
16, UTIL_SLAB_SINGLETHREADED);
|
||||
vc4->blitter = util_blitter_create(pctx);
|
||||
if (!vc4->blitter)
|
||||
goto fail;
|
||||
|
||||
return &vc4->base;
|
||||
|
||||
fail:
|
||||
pctx->destroy(pctx);
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef VC4_CONTEXT_H
|
||||
#define VC4_CONTEXT_H
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/u_slab.h"
|
||||
|
||||
#include "vc4_bufmgr.h"
|
||||
#include "vc4_resource.h"
|
||||
#include "vc4_cl.h"
|
||||
|
||||
#define VC4_DIRTY_BLEND (1 << 0)
|
||||
#define VC4_DIRTY_RASTERIZER (1 << 1)
|
||||
#define VC4_DIRTY_ZSA (1 << 2)
|
||||
#define VC4_DIRTY_FRAGTEX (1 << 3)
|
||||
#define VC4_DIRTY_VERTTEX (1 << 4)
|
||||
#define VC4_DIRTY_TEXSTATE (1 << 5)
|
||||
#define VC4_DIRTY_PROG (1 << 6)
|
||||
#define VC4_DIRTY_BLEND_COLOR (1 << 7)
|
||||
#define VC4_DIRTY_STENCIL_REF (1 << 8)
|
||||
#define VC4_DIRTY_SAMPLE_MASK (1 << 9)
|
||||
#define VC4_DIRTY_FRAMEBUFFER (1 << 10)
|
||||
#define VC4_DIRTY_STIPPLE (1 << 11)
|
||||
#define VC4_DIRTY_VIEWPORT (1 << 12)
|
||||
#define VC4_DIRTY_CONSTBUF (1 << 13)
|
||||
#define VC4_DIRTY_VTXSTATE (1 << 14)
|
||||
#define VC4_DIRTY_VTXBUF (1 << 15)
|
||||
#define VC4_DIRTY_INDEXBUF (1 << 16)
|
||||
#define VC4_DIRTY_SCISSOR (1 << 17)
|
||||
|
||||
#define VC4_SHADER_DIRTY_VP (1 << 0)
|
||||
#define VC4_SHADER_DIRTY_FP (1 << 1)
|
||||
|
||||
struct vc4_texture_stateobj {
|
||||
struct pipe_sampler_view *textures[PIPE_MAX_SAMPLERS];
|
||||
unsigned num_textures;
|
||||
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
|
||||
unsigned num_samplers;
|
||||
unsigned dirty_samplers;
|
||||
};
|
||||
|
||||
struct vc4_shader_state {
|
||||
struct pipe_shader_state base;
|
||||
struct vc4_bo *bo;
|
||||
};
|
||||
|
||||
struct vc4_program_stateobj {
|
||||
struct vc4_shader_state *vs, *fs;
|
||||
uint32_t dirty;
|
||||
uint8_t num_exports;
|
||||
/* Indexed by semantic name or TGSI_SEMANTIC_COUNT + semantic index
|
||||
* for TGSI_SEMANTIC_GENERIC. Special vs exports (position and point-
|
||||
* size) are not included in this
|
||||
*/
|
||||
uint8_t export_linkage[63];
|
||||
};
|
||||
|
||||
struct vc4_constbuf_stateobj {
|
||||
struct pipe_constant_buffer cb[PIPE_MAX_CONSTANT_BUFFERS];
|
||||
uint32_t enabled_mask;
|
||||
uint32_t dirty_mask;
|
||||
};
|
||||
|
||||
struct vc4_vertexbuf_stateobj {
|
||||
struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS];
|
||||
unsigned count;
|
||||
uint32_t enabled_mask;
|
||||
uint32_t dirty_mask;
|
||||
};
|
||||
|
||||
struct vc4_vertex_stateobj {
|
||||
struct pipe_vertex_element pipe[PIPE_MAX_ATTRIBS];
|
||||
unsigned num_elements;
|
||||
};
|
||||
|
||||
struct vc4_context {
|
||||
struct pipe_context base;
|
||||
|
||||
int fd;
|
||||
struct vc4_screen *screen;
|
||||
|
||||
struct vc4_cl bcl;
|
||||
struct vc4_cl rcl;
|
||||
struct vc4_cl shader_rec;
|
||||
struct vc4_cl bo_handles;
|
||||
uint32_t shader_rec_count;
|
||||
|
||||
struct util_slab_mempool transfer_pool;
|
||||
struct blitter_context *blitter;
|
||||
|
||||
/** bitfield of VC4_DIRTY_* */
|
||||
uint32_t dirty;
|
||||
|
||||
/**
|
||||
* Set if some drawing (triangles, blits, or just a glClear()) has
|
||||
* been done to the FBO, meaning that we need to
|
||||
* DRM_IOCTL_VC4_SUBMIT_CL.
|
||||
*/
|
||||
bool needs_flush;
|
||||
|
||||
/** @{ Current pipeline state objects */
|
||||
struct pipe_scissor_state scissor;
|
||||
struct pipe_blend_state *blend;
|
||||
struct vc4_rasterizer_state *rasterizer;
|
||||
struct pipe_depth_stencil_alpha_state *zsa;
|
||||
|
||||
struct vc4_texture_stateobj verttex, fragtex;
|
||||
|
||||
struct vc4_program_stateobj prog;
|
||||
|
||||
struct vc4_vertex_stateobj *vtx;
|
||||
|
||||
struct pipe_blend_color blend_color;
|
||||
struct pipe_stencil_ref stencil_ref;
|
||||
unsigned sample_mask;
|
||||
struct pipe_framebuffer_state framebuffer;
|
||||
struct pipe_poly_stipple stipple;
|
||||
struct pipe_viewport_state viewport;
|
||||
struct vc4_constbuf_stateobj constbuf[PIPE_SHADER_TYPES];
|
||||
struct vc4_vertexbuf_stateobj vertexbuf;
|
||||
struct pipe_index_buffer indexbuf;
|
||||
/** @} */
|
||||
};
|
||||
|
||||
struct vc4_rasterizer_state {
|
||||
struct pipe_rasterizer_state base;
|
||||
|
||||
/* VC4_CONFIGURATION_BITS */
|
||||
uint8_t config_bits[3];
|
||||
|
||||
float point_size;
|
||||
};
|
||||
|
||||
static inline struct vc4_context *
|
||||
vc4_context(struct pipe_context *pcontext)
|
||||
{
|
||||
return (struct vc4_context *)pcontext;
|
||||
}
|
||||
|
||||
struct pipe_context *vc4_context_create(struct pipe_screen *pscreen,
|
||||
void *priv);
|
||||
void vc4_draw_init(struct pipe_context *pctx);
|
||||
void vc4_state_init(struct pipe_context *pctx);
|
||||
void vc4_program_init(struct pipe_context *pctx);
|
||||
void vc4_simulator_init(struct vc4_screen *screen);
|
||||
void vc4_simulator_flush(struct vc4_context *vc4,
|
||||
struct vc4_surface *color_surf);
|
||||
void *vc4_simulator_alloc(struct vc4_screen *screen, uint32_t size);
|
||||
|
||||
void vc4_flush(struct pipe_context *pctx);
|
||||
void vc4_emit_state(struct pipe_context *pctx);
|
||||
|
||||
#endif /* VC4_CONTEXT_H */
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Scott Mansell
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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 "vc4_context.h"
|
||||
#include "vc4_resource.h"
|
||||
|
||||
static struct vc4_bo *
|
||||
get_vbo(struct vc4_context *vc4, uint32_t width, uint32_t height)
|
||||
{
|
||||
struct {
|
||||
uint16_t x, y;
|
||||
float z, rhw, r, g, b;
|
||||
} verts[] = {
|
||||
{
|
||||
// Vertex: Top, red
|
||||
(-(int)width / 3) << 4, // X in 12.4 fixed point
|
||||
(-(int)height / 3) << 4, // Y in 12.4 fixed point
|
||||
1.0f, // Z
|
||||
1.0f, // 1/W
|
||||
1.0f, // Varying 0 (Red)
|
||||
0.0f, // Varying 1 (Green)
|
||||
0.0f, // Varying 2 (Blue)
|
||||
},
|
||||
{
|
||||
// Vertex: bottom left, Green
|
||||
(width / 3) << 4, // X in 12.4 fixed point
|
||||
(-(int)height / 3) << 4, // Y in 12.4 fixed point
|
||||
1.0f, // Z
|
||||
1.0f, // 1/W
|
||||
0.0f, // Varying 0 (Red)
|
||||
1.0f, // Varying 1 (Green)
|
||||
0.0f, // Varying 2 (Blue)
|
||||
},
|
||||
|
||||
{
|
||||
// Vertex: bottom right, Blue
|
||||
(width / 3) << 4, // X in 12.4 fixed point
|
||||
(height / 3) << 4, // Y in 12.4 fixed point
|
||||
1.0f, // Z
|
||||
1.0f, // 1/W
|
||||
0.0f, // Varying 0 (Red)
|
||||
0.0f, // Varying 1 (Green)
|
||||
1.0f, // Varying 2 (Blue)
|
||||
},
|
||||
};
|
||||
|
||||
return vc4_bo_alloc_mem(vc4->screen, verts, sizeof(verts), "verts");
|
||||
}
|
||||
static struct vc4_bo *
|
||||
get_ibo(struct vc4_context *vc4)
|
||||
{
|
||||
static const uint8_t indices[] = { 0, 1, 2 };
|
||||
|
||||
return vc4_bo_alloc_mem(vc4->screen, indices, sizeof(indices), "indices");
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_rcl_tile_calls(struct vc4_context *vc4,
|
||||
uint32_t xtiles, uint32_t ytiles,
|
||||
struct vc4_bo *tile_alloc)
|
||||
{
|
||||
for (int x = 0; x < xtiles; x++) {
|
||||
for (int y = 0; y < ytiles; y++) {
|
||||
cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES);
|
||||
cl_u8(&vc4->rcl, x);
|
||||
cl_u8(&vc4->rcl, y);
|
||||
|
||||
cl_start_reloc(&vc4->rcl, 1);
|
||||
cl_u8(&vc4->rcl, VC4_PACKET_BRANCH_TO_SUB_LIST);
|
||||
cl_reloc(vc4, &vc4->rcl, tile_alloc,
|
||||
(y * xtiles + x) * 32);
|
||||
|
||||
if (x == xtiles - 1 && y == ytiles - 1) {
|
||||
cl_u8(&vc4->rcl,
|
||||
VC4_PACKET_STORE_MS_TILE_BUFFER_AND_EOF);
|
||||
} else {
|
||||
cl_u8(&vc4->rcl,
|
||||
VC4_PACKET_STORE_MS_TILE_BUFFER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
uint32_t width = vc4->framebuffer.width;
|
||||
uint32_t height = vc4->framebuffer.height;
|
||||
uint32_t tilew = align(width, 64) / 64;
|
||||
uint32_t tileh = align(height, 64) / 64;
|
||||
struct vc4_bo *tile_alloc = vc4_bo_alloc(vc4->screen,
|
||||
32 * tilew * tileh, "tilea");
|
||||
struct vc4_bo *tile_state = vc4_bo_alloc(vc4->screen,
|
||||
48 * tilew * tileh, "tilestate");
|
||||
struct vc4_bo *ibo = get_ibo(vc4);
|
||||
|
||||
struct vc4_bo *fs_uniform = vc4_bo_alloc(vc4->screen, 0x1000, "fsu");
|
||||
struct vc4_bo *vbo = get_vbo(vc4, width, height);
|
||||
|
||||
vc4->needs_flush = true;
|
||||
|
||||
// Tile state data is 48 bytes per tile, I think it can be thrown away
|
||||
// as soon as binning is finished.
|
||||
cl_start_reloc(&vc4->bcl, 2);
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_TILE_BINNING_MODE_CONFIG);
|
||||
cl_reloc(vc4, &vc4->bcl, tile_alloc, 0);
|
||||
cl_u32(&vc4->bcl, 0x8000); /* tile allocation memory size */
|
||||
cl_reloc(vc4, &vc4->bcl, tile_state, 0);
|
||||
cl_u8(&vc4->bcl, tilew);
|
||||
cl_u8(&vc4->bcl, tileh);
|
||||
cl_u8(&vc4->bcl, VC4_BIN_CONFIG_AUTO_INIT_TSDA);
|
||||
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_START_TILE_BINNING);
|
||||
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_PRIMITIVE_LIST_FORMAT);
|
||||
cl_u8(&vc4->bcl, 0x32); // 16 bit triangle
|
||||
|
||||
vc4_emit_state(pctx);
|
||||
|
||||
/* the actual draw call. */
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_NV_SHADER_STATE);
|
||||
#ifndef USE_VC4_SIMULATOR
|
||||
cl_u32(&vc4->bcl, 0); /* offset into shader_rec */
|
||||
#else
|
||||
cl_u32(&vc4->bcl, simpenrose_hw_addr(vc4->shader_rec.next));
|
||||
#endif
|
||||
|
||||
cl_start_reloc(&vc4->bcl, 1);
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_GL_INDEXED_PRIMITIVE);
|
||||
cl_u8(&vc4->bcl, 0x04); // 8bit index, trinagles
|
||||
cl_u32(&vc4->bcl, 3); // Length
|
||||
cl_reloc(vc4, &vc4->bcl, ibo, 0);
|
||||
cl_u32(&vc4->bcl, 2); // Maximum index
|
||||
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_FLUSH_ALL);
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_NOP);
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_HALT);
|
||||
|
||||
// Shader Record
|
||||
cl_start_shader_reloc(&vc4->shader_rec, 3);
|
||||
|
||||
cl_u8(&vc4->shader_rec, 0);
|
||||
cl_u8(&vc4->shader_rec, 6*4); // stride
|
||||
cl_u8(&vc4->shader_rec, 0xcc); // num uniforms (not used)
|
||||
cl_u8(&vc4->shader_rec, 3); // num varyings
|
||||
cl_reloc(vc4, &vc4->shader_rec, vc4->prog.fs->bo, 0);
|
||||
cl_reloc(vc4, &vc4->shader_rec, fs_uniform, 0);
|
||||
cl_reloc(vc4, &vc4->shader_rec, vbo, 0);
|
||||
|
||||
vc4->shader_rec_count++;
|
||||
|
||||
cl_u8(&vc4->rcl, VC4_PACKET_CLEAR_COLORS);
|
||||
cl_u32(&vc4->rcl, 0xff000000); // Opaque Black
|
||||
cl_u32(&vc4->rcl, 0xff000000); // 32 bit clear colours need to be repeated twice
|
||||
cl_u32(&vc4->rcl, 0);
|
||||
cl_u8(&vc4->rcl, 0);
|
||||
|
||||
struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]);
|
||||
struct vc4_resource *ctex = vc4_resource(csurf->base.texture);
|
||||
|
||||
cl_start_reloc(&vc4->rcl, 1);
|
||||
cl_u8(&vc4->rcl, VC4_PACKET_TILE_RENDERING_MODE_CONFIG);
|
||||
cl_reloc(vc4, &vc4->rcl, ctex->bo, csurf->offset);
|
||||
cl_u16(&vc4->rcl, width);
|
||||
cl_u16(&vc4->rcl, height);
|
||||
cl_u8(&vc4->rcl, (VC4_RENDER_CONFIG_MEMORY_FORMAT_LINEAR |
|
||||
VC4_RENDER_CONFIG_FORMAT_RGBA8888));
|
||||
cl_u8(&vc4->rcl, 0);
|
||||
|
||||
// Do a store of the first tile to force the tile buffer to be cleared
|
||||
/* XXX: I think these two packets may be unnecessary. */
|
||||
cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES);
|
||||
cl_u8(&vc4->rcl, 0);
|
||||
cl_u8(&vc4->rcl, 0);
|
||||
|
||||
cl_u8(&vc4->rcl, VC4_PACKET_STORE_TILE_BUFFER_GENERAL);
|
||||
cl_u16(&vc4->rcl, 0); // Store nothing (just clear)
|
||||
cl_u32(&vc4->rcl, 0); // no address is needed
|
||||
|
||||
vc4_rcl_tile_calls(vc4, tilew, tileh, tile_alloc);
|
||||
|
||||
vc4_flush(pctx);
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_clear(struct pipe_context *pctx, unsigned buffers,
|
||||
const union pipe_color_union *color, double depth, unsigned stencil)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
|
||||
vc4->needs_flush = true;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps,
|
||||
const union pipe_color_union *color,
|
||||
unsigned x, unsigned y, unsigned w, unsigned h)
|
||||
{
|
||||
fprintf(stderr, "unimpl: clear RT\n");
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps,
|
||||
unsigned buffers, double depth, unsigned stencil,
|
||||
unsigned x, unsigned y, unsigned w, unsigned h)
|
||||
{
|
||||
fprintf(stderr, "unimpl: clear DS\n");
|
||||
}
|
||||
|
||||
void
|
||||
vc4_draw_init(struct pipe_context *pctx)
|
||||
{
|
||||
pctx->draw_vbo = vc4_draw_vbo;
|
||||
pctx->clear = vc4_clear;
|
||||
pctx->clear_render_target = vc4_clear_render_target;
|
||||
pctx->clear_depth_stencil = vc4_clear_depth_stencil;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_VC4_DRM_H_
|
||||
#define _UAPI_VC4_DRM_H_
|
||||
|
||||
#include <drm.h>
|
||||
|
||||
#define DRM_VC4_SUBMIT_CL 0x00
|
||||
|
||||
#define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR( DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl)
|
||||
|
||||
struct drm_vc4_submit_cl {
|
||||
void __user *bin_cl;
|
||||
void __user *render_cl;
|
||||
void __user *shader_records;
|
||||
void __user *bo_handles;
|
||||
uint32_t bin_cl_len;
|
||||
uint32_t render_cl_len;
|
||||
uint32_t shader_record_len;
|
||||
uint32_t shader_record_count;
|
||||
uint32_t bo_handle_count;
|
||||
};
|
||||
|
||||
#endif /* _UAPI_VC4_DRM_H_ */
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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 "vc4_context.h"
|
||||
|
||||
void
|
||||
vc4_emit_state(struct pipe_context *pctx)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
|
||||
if (vc4->dirty & VC4_DIRTY_SCISSOR) {
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_CLIP_WINDOW);
|
||||
cl_u16(&vc4->bcl, vc4->scissor.minx);
|
||||
cl_u16(&vc4->bcl, vc4->scissor.miny);
|
||||
cl_u16(&vc4->bcl, vc4->scissor.maxx - vc4->scissor.minx);
|
||||
cl_u16(&vc4->bcl, vc4->scissor.maxy - vc4->scissor.miny);
|
||||
}
|
||||
|
||||
if (vc4->dirty & VC4_DIRTY_RASTERIZER) {
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_CONFIGURATION_BITS);
|
||||
cl_u8(&vc4->bcl, vc4->rasterizer->config_bits[0]);
|
||||
cl_u8(&vc4->bcl, vc4->rasterizer->config_bits[1]);
|
||||
cl_u8(&vc4->bcl, vc4->rasterizer->config_bits[2]);
|
||||
}
|
||||
|
||||
if (vc4->dirty & VC4_DIRTY_VIEWPORT) {
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_CLIPPER_XY_SCALING);
|
||||
cl_f(&vc4->bcl, vc4->viewport.scale[0] * 16.0f);
|
||||
cl_f(&vc4->bcl, vc4->viewport.scale[1] * 16.0f);
|
||||
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_CLIPPER_Z_SCALING);
|
||||
cl_f(&vc4->bcl, vc4->viewport.translate[2]);
|
||||
cl_f(&vc4->bcl, vc4->viewport.scale[2]);
|
||||
|
||||
cl_u8(&vc4->bcl, VC4_PACKET_VIEWPORT_OFFSET);
|
||||
cl_u16(&vc4->bcl, 16 * vc4->viewport.translate[0]);
|
||||
cl_u16(&vc4->bcl, 16 * vc4->viewport.translate[1]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef VC4_PACKET_H
|
||||
#define VC4_PACKET_H
|
||||
|
||||
enum vc4_packet {
|
||||
VC4_PACKET_HALT = 0,
|
||||
VC4_PACKET_NOP = 1,
|
||||
|
||||
VC4_PACKET_FLUSH = 4,
|
||||
VC4_PACKET_FLUSH_ALL = 5,
|
||||
VC4_PACKET_START_TILE_BINNING = 6,
|
||||
VC4_PACKET_INCREMENT_SEMAPHORE = 7,
|
||||
VC4_PACKET_WAIT_ON_SEMAPHORE = 8,
|
||||
|
||||
VC4_PACKET_BRANCH = 16,
|
||||
VC4_PACKET_BRANCH_TO_SUB_LIST = 17,
|
||||
|
||||
VC4_PACKET_STORE_MS_TILE_BUFFER = 24,
|
||||
VC4_PACKET_STORE_MS_TILE_BUFFER_AND_EOF = 25,
|
||||
VC4_PACKET_STORE_FULL_RES_TILE_BUFFER = 26,
|
||||
VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER = 27,
|
||||
VC4_PACKET_STORE_TILE_BUFFER_GENERAL = 28,
|
||||
VC4_PACKET_LOAD_TILE_BUFFER_GENERAL = 29,
|
||||
|
||||
VC4_PACKET_GL_INDEXED_PRIMITIVE = 32,
|
||||
VC4_PACKET_GL_ARRAY_PRIMITIVE = 33,
|
||||
|
||||
VC4_PACKET_COMPRESSED_PRIMITIVE = 48,
|
||||
VC4_PACKET_CLIPPED_COMPRESSED_PRIMITIVE = 49,
|
||||
|
||||
VC4_PACKET_PRIMITIVE_LIST_FORMAT = 56,
|
||||
|
||||
VC4_PACKET_GL_SHADER_STATE = 64,
|
||||
VC4_PACKET_NV_SHADER_STATE = 65,
|
||||
VC4_PACKET_VG_SHADER_STATE = 66,
|
||||
|
||||
VC4_PACKET_CONFIGURATION_BITS = 96,
|
||||
VC4_PACKET_FLAT_SHADE_FLAGS = 97,
|
||||
VC4_PACKET_POINT_SIZE = 98,
|
||||
VC4_PACKET_LINE_WIDTH = 99,
|
||||
VC4_PACKET_RHT_X_BOUNDARY = 100,
|
||||
VC4_PACKET_DEPTH_OFFSET = 101,
|
||||
VC4_PACKET_CLIP_WINDOW = 102,
|
||||
VC4_PACKET_VIEWPORT_OFFSET = 103,
|
||||
VC4_PACKET_Z_CLIPPING = 104,
|
||||
VC4_PACKET_CLIPPER_XY_SCALING = 105,
|
||||
VC4_PACKET_CLIPPER_Z_SCALING = 106,
|
||||
|
||||
VC4_PACKET_TILE_BINNING_MODE_CONFIG = 112,
|
||||
VC4_PACKET_TILE_RENDERING_MODE_CONFIG = 113,
|
||||
VC4_PACKET_CLEAR_COLORS = 114,
|
||||
VC4_PACKET_TILE_COORDINATES = 115,
|
||||
GEM_HANDLES = 254,
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/** @{
|
||||
* byte 2 of VC4_PACKET_STORE_TILE_BUFFER_GENERAL (low bits of the
|
||||
* address)
|
||||
*/
|
||||
|
||||
#define VC4_STORE_TILE_BUFFER_DISABLE_FULL_VG_MASK_DUMP (1 << 2)
|
||||
#define VC4_STORE_TILE_BUFFER_DISABLE_FULL_ZS_DUMP (1 << 1)
|
||||
#define VC4_STORE_TILE_BUFFER_DISABLE_FULL_COLOR_DUMP (1 << 0)
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @{ byte 1 of VC4_PACKET_STORE_TILE_BUFFER_GENERAL */
|
||||
#define VC4_STORE_TILE_BUFFER_DISABLE_VG_MASK_CLEAR (1 << 7)
|
||||
#define VC4_STORE_TILE_BUFFER_DISABLE_ZS_CLEAR (1 << 6)
|
||||
#define VC4_STORE_TILE_BUFFER_DISABLE_COLOR_CLEAR (1 << 5)
|
||||
#define VC4_STORE_TILE_BUFFER_DISABLE_SWAP (1 << 4)
|
||||
|
||||
#define VC4_STORE_TILE_BUFFER_RGBA8888 (0 << 0)
|
||||
#define VC4_STORE_TILE_BUFFER_BGR565_DITHER (1 << 0)
|
||||
#define VC4_STORE_TILE_BUFFER_BGR565 (2 << 0)
|
||||
/** @} */
|
||||
|
||||
/** @{ byte 0 of VC4_PACKET_STORE_TILE_BUFFER_GENERAL */
|
||||
#define VC4_STORE_TILE_BUFFER_MODE_SAMPLE0 (0 << 6)
|
||||
#define VC4_STORE_TILE_BUFFER_MODE_DECIMATE_X4 (1 << 6)
|
||||
#define VC4_STORE_TILE_BUFFER_MODE_DECIMATE_X16 (2 << 6)
|
||||
|
||||
#define VC4_STORE_TILE_BUFFER_FORMAT_RASTER (0 << 4)
|
||||
#define VC4_STORE_TILE_BUFFER_FORMAT_T (1 << 4)
|
||||
#define VC4_STORE_TILE_BUFFER_FORMAT_LT (2 << 4)
|
||||
|
||||
#define VC4_STORE_TILE_BUFFER_NONE (0 << 0)
|
||||
#define VC4_STORE_TILE_BUFFER_COLOR (1 << 0)
|
||||
#define VC4_STORE_TILE_BUFFER_ZS (2 << 0)
|
||||
#define VC4_STORE_TILE_BUFFER_Z (3 << 0)
|
||||
#define VC4_STORE_TILE_BUFFER_VG_MASK (4 << 0)
|
||||
#define VC4_STORE_TILE_BUFFER_FULL (5 << 0)
|
||||
/** @} */
|
||||
|
||||
/* This flag is only present in NV shader state. */
|
||||
#define VC4_SHADER_FLAG_SHADED_CLIP_COORDS (1 << 3)
|
||||
#define VC4_SHADER_FLAG_ENABLE_CLIPPING (1 << 2)
|
||||
#define VC4_SHADER_FLAG_VS_POINT_SIZE (1 << 1)
|
||||
#define VC4_SHADER_FLAG_FS_SINGLE_THREAD (1 << 0)
|
||||
|
||||
/** @{ byte 2 of config bits. */
|
||||
#define VC4_CONFIG_BITS_EARLY_Z_UPDATE (1 << 1)
|
||||
#define VC4_CONFIG_BITS_EARLY_Z (1 << 0)
|
||||
/** @} */
|
||||
|
||||
/** @{ byte 1 of config bits. */
|
||||
#define VC4_CONFIG_BITS_Z_UPDATE (1 << 7)
|
||||
/** same values in this 3-bit field as PIPE_FUNC_* */
|
||||
#define VC4_CONFIG_BITS_DEPTH_FUNC_SHIFT 4
|
||||
#define VC4_CONFIG_BITS_COVERAGE_READ_LEAVE (1 << 3)
|
||||
|
||||
#define VC4_CONFIG_BITS_COVERAGE_UPDATE_NONZERO (0 << 1)
|
||||
#define VC4_CONFIG_BITS_COVERAGE_UPDATE_ODD (1 << 1)
|
||||
#define VC4_CONFIG_BITS_COVERAGE_UPDATE_OR (2 << 1)
|
||||
#define VC4_CONFIG_BITS_COVERAGE_UPDATE_ZERO (3 << 1)
|
||||
|
||||
#define VC4_CONFIG_BITS_COVERAGE_PIPE_SELECT (1 << 0)
|
||||
/** @} */
|
||||
|
||||
/** @{ byte 0 of config bits. */
|
||||
#define VC4_CONFIG_BITS_RASTERIZER_OVERSAMPLE_NONE (0 << 6)
|
||||
#define VC4_CONFIG_BITS_RASTERIZER_OVERSAMPLE_4X (1 << 6)
|
||||
#define VC4_CONFIG_BITS_RASTERIZER_OVERSAMPLE_16X (2 << 6)
|
||||
|
||||
#define VC4_CONFIG_BITS_AA_POINTS_AND_LINES (1 << 4)
|
||||
#define VC4_CONFIG_BITS_ENABLE_DEPTH_OFFSET (1 << 3)
|
||||
#define VC4_CONFIG_BITS_CW_PRIMITIVES (1 << 2)
|
||||
#define VC4_CONFIG_BITS_ENABLE_PRIM_BACK (1 << 1)
|
||||
#define VC4_CONFIG_BITS_ENABLE_PRIM_FRONT (1 << 0)
|
||||
/** @} */
|
||||
|
||||
/** @{ bits in the last u8 of VC4_PACKET_TILE_BINNING_MODE_CONFIG */
|
||||
#define VC4_BIN_CONFIG_DB_NON_MS (1 << 7)
|
||||
|
||||
#define VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_32 (0 << 5)
|
||||
#define VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_64 (1 << 5)
|
||||
#define VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_128 (2 << 5)
|
||||
#define VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_256 (3 << 5)
|
||||
|
||||
#define VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_32 (0 << 3)
|
||||
#define VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_64 (1 << 3)
|
||||
#define VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_128 (2 << 3)
|
||||
#define VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_256 (3 << 3)
|
||||
|
||||
#define VC4_BIN_CONFIG_AUTO_INIT_TSDA (1 << 2)
|
||||
#define VC4_BIN_CONFIG_TILE_BUFFER_64BIT (1 << 1)
|
||||
#define VC4_BIN_CONFIG_MS_MODE_4X (1 << 0)
|
||||
/** @} */
|
||||
|
||||
/** @{ bits in the last u16 of VC4_PACKET_TILE_RENDERING_MODE_CONFIG */
|
||||
#define VC4_RENDER_CONFIG_DB_NON_MS (1 << 12)
|
||||
#define VC4_RENDER_CONFIG_EARLY_Z_COVERAGE_DISABLE (1 << 11)
|
||||
#define VC4_RENDER_CONFIG_EARLY_Z_DIRECTION_G (1 << 10)
|
||||
#define VC4_RENDER_CONFIG_COVERAGE_MODE (1 << 9)
|
||||
#define VC4_RENDER_CONFIG_ENABLE_VG_MASK (1 << 8)
|
||||
|
||||
#define VC4_RENDER_CONFIG_MEMORY_FORMAT_LINEAR (0 << 6)
|
||||
#define VC4_RENDER_CONFIG_MEMORY_FORMAT_T (1 << 6)
|
||||
#define VC4_RENDER_CONFIG_MEMORY_FORMAT_LT (2 << 6)
|
||||
|
||||
#define VC4_RENDER_CONFIG_DECIMATE_MODE_1X (0 << 4)
|
||||
#define VC4_RENDER_CONFIG_DECIMATE_MODE_4X (1 << 4)
|
||||
#define VC4_RENDER_CONFIG_DECIMATE_MODE_16X (2 << 4)
|
||||
|
||||
#define VC4_RENDER_CONFIG_FORMAT_BGR565 (0 << 2)
|
||||
#define VC4_RENDER_CONFIG_FORMAT_RGBA8888 (1 << 2)
|
||||
#define VC4_RENDER_CONFIG_FORMAT_BGR565_DITHERED (2 << 2)
|
||||
|
||||
#define VC4_RENDER_CONFIG_TILE_BUFFER_64BIT (1 << 1)
|
||||
#define VC4_RENDER_CONFIG_MS_MODE_4X (1 << 0)
|
||||
|
||||
#endif /* VC4_PACKET_H */
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Scott Mansell
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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 <inttypes.h>
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "tgsi/tgsi_parse.h"
|
||||
|
||||
#include "vc4_context.h"
|
||||
#include "vc4_qpu.h"
|
||||
|
||||
static void
|
||||
vc4_dump_program(const uint64_t *insts, uint count)
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
fprintf(stderr, "0x%016"PRIx64" ", insts[i]);
|
||||
vc4_qpu_disasm(&insts[i], 1);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
static struct vc4_shader_state *
|
||||
vc4_shader_state_create(struct pipe_context *pctx,
|
||||
const struct pipe_shader_state *cso)
|
||||
{
|
||||
struct vc4_shader_state *so = CALLOC_STRUCT(vc4_shader_state);
|
||||
if (!so)
|
||||
return NULL;
|
||||
|
||||
so->base.tokens = tgsi_dup_tokens(cso->tokens);
|
||||
|
||||
return so;
|
||||
}
|
||||
|
||||
static void *
|
||||
vc4_fs_state_create(struct pipe_context *pctx,
|
||||
const struct pipe_shader_state *cso)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
struct vc4_shader_state *so = vc4_shader_state_create(pctx, cso);
|
||||
if (!so)
|
||||
return NULL;
|
||||
|
||||
uint64_t gen_fsc[100];
|
||||
uint64_t cur_inst;
|
||||
int gen_fsc_len = 0;
|
||||
#if 1
|
||||
cur_inst = qpu_load_imm_f(qpu_r5(), 0.0f);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_MOV(qpu_r0(), qpu_vary()),
|
||||
qpu_m_MOV(qpu_r3(), qpu_r5()));
|
||||
cur_inst |= QPU_PM;
|
||||
cur_inst |= QPU_SET_FIELD(QPU_PACK_MUL_8D, QPU_PACK);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_FADD(qpu_r0(), qpu_r0(), qpu_r5()),
|
||||
qpu_m_MOV(qpu_r1(), qpu_vary()));
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_FADD(qpu_r1(), qpu_r1(), qpu_r5()),
|
||||
qpu_m_MOV(qpu_r2(), qpu_vary()));
|
||||
cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_WAIT_FOR_SCOREBOARD, QPU_SIG);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_FADD(qpu_r2(), qpu_r2(), qpu_r5()),
|
||||
qpu_m_MOV(qpu_r3(), qpu_r0()));
|
||||
cur_inst |= QPU_PM;
|
||||
cur_inst |= QPU_SET_FIELD(QPU_PACK_MUL_8A, QPU_PACK);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_NOP(),
|
||||
qpu_m_MOV(qpu_r3(), qpu_r1()));
|
||||
cur_inst |= QPU_PM;
|
||||
cur_inst |= QPU_SET_FIELD(QPU_PACK_MUL_8B, QPU_PACK);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_NOP(),
|
||||
qpu_m_MOV(qpu_r3(), qpu_r2()));
|
||||
cur_inst |= QPU_PM;
|
||||
cur_inst |= QPU_SET_FIELD(QPU_PACK_MUL_8C, QPU_PACK);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_MOV(qpu_tlbc(), qpu_r3()),
|
||||
qpu_m_NOP());
|
||||
cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_PROG_END, QPU_SIG);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP());
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP());
|
||||
cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_SCOREBOARD_UNLOCK, QPU_SIG);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
#else
|
||||
|
||||
/* drain the varyings. */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
cur_inst = qpu_inst(qpu_a_MOV(qpu_ra(QPU_W_NOP), qpu_rb(QPU_R_NOP)),
|
||||
qpu_m_NOP());
|
||||
if (i == 1)
|
||||
cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_WAIT_FOR_SCOREBOARD, QPU_SIG);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP());
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
}
|
||||
|
||||
/* some colors */
|
||||
#if 1
|
||||
for (int i = 0; i < 4; i++) {
|
||||
cur_inst = qpu_load_imm_f(qpu_rn(i), .2 + i / 4.0);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
cur_inst = qpu_inst(qpu_a_NOP(),
|
||||
qpu_m_FMUL(qpu_ra(1),
|
||||
qpu_rn(i), qpu_rn(i)));
|
||||
cur_inst |= QPU_PM;
|
||||
cur_inst |= QPU_SET_FIELD(QPU_PACK_A_8A + i, QPU_PACK);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
}
|
||||
#else
|
||||
cur_inst = qpu_load_imm_ui(qpu_ra(1), 0x22446688);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
#endif
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP());
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_MOV(qpu_tlbc(), qpu_ra(1)),
|
||||
qpu_m_NOP());
|
||||
cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_PROG_END, QPU_SIG);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP());
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
|
||||
cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP());
|
||||
cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_SCOREBOARD_UNLOCK, QPU_SIG);
|
||||
gen_fsc[gen_fsc_len++] = cur_inst;
|
||||
#endif
|
||||
|
||||
|
||||
if (1)
|
||||
vc4_dump_program(gen_fsc, gen_fsc_len);
|
||||
vc4_qpu_validate(gen_fsc, gen_fsc_len);
|
||||
|
||||
so->bo = vc4_bo_alloc_mem(vc4->screen, gen_fsc,
|
||||
gen_fsc_len * sizeof(uint64_t), "fs_code");
|
||||
|
||||
return so;
|
||||
}
|
||||
|
||||
static void *
|
||||
vc4_vs_state_create(struct pipe_context *pctx,
|
||||
const struct pipe_shader_state *cso)
|
||||
{
|
||||
struct vc4_shader_state *so = vc4_shader_state_create(pctx, cso);
|
||||
if (!so)
|
||||
return NULL;
|
||||
|
||||
|
||||
return so;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_shader_state_delete(struct pipe_context *pctx, void *hwcso)
|
||||
{
|
||||
struct pipe_shader_state *so = hwcso;
|
||||
|
||||
free((void *)so->tokens);
|
||||
free(so);
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_fp_state_bind(struct pipe_context *pctx, void *hwcso)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
vc4->prog.fs = hwcso;
|
||||
vc4->prog.dirty |= VC4_SHADER_DIRTY_FP;
|
||||
vc4->dirty |= VC4_DIRTY_PROG;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_vp_state_bind(struct pipe_context *pctx, void *hwcso)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
vc4->prog.vs = hwcso;
|
||||
vc4->prog.dirty |= VC4_SHADER_DIRTY_VP;
|
||||
vc4->dirty |= VC4_DIRTY_PROG;
|
||||
}
|
||||
|
||||
void
|
||||
vc4_program_init(struct pipe_context *pctx)
|
||||
{
|
||||
pctx->create_vs_state = vc4_vs_state_create;
|
||||
pctx->delete_vs_state = vc4_shader_state_delete;
|
||||
|
||||
pctx->create_fs_state = vc4_fs_state_create;
|
||||
pctx->delete_fs_state = vc4_shader_state_delete;
|
||||
|
||||
pctx->bind_fs_state = vc4_fp_state_bind;
|
||||
pctx->bind_vs_state = vc4_vp_state_bind;
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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 <stdbool.h>
|
||||
#include "vc4_qpu.h"
|
||||
|
||||
static uint64_t
|
||||
set_src_raddr(uint64_t inst, struct qpu_reg src)
|
||||
{
|
||||
if (src.mux == QPU_MUX_A) {
|
||||
/* These asserts could be better, checking to be sure we're
|
||||
* not overwriting an actual use of a raddr of 0.
|
||||
*/
|
||||
assert(QPU_GET_FIELD(inst, QPU_RADDR_A) == 0 ||
|
||||
QPU_GET_FIELD(inst, QPU_RADDR_A) == src.addr);
|
||||
return inst | QPU_SET_FIELD(src.addr, QPU_RADDR_A);
|
||||
}
|
||||
|
||||
if (src.mux == QPU_MUX_B) {
|
||||
assert(QPU_GET_FIELD(inst, QPU_RADDR_B) == 0 ||
|
||||
QPU_GET_FIELD(inst, QPU_RADDR_B) == src.addr);
|
||||
return inst | QPU_SET_FIELD(src.addr, QPU_RADDR_B);
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
qpu_a_NOP()
|
||||
{
|
||||
uint64_t inst = 0;
|
||||
|
||||
inst |= QPU_SET_FIELD(QPU_A_NOP, QPU_OP_ADD);
|
||||
inst |= QPU_SET_FIELD(QPU_W_NOP, QPU_WADDR_ADD);
|
||||
inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
qpu_m_NOP()
|
||||
{
|
||||
uint64_t inst = 0;
|
||||
|
||||
inst |= QPU_SET_FIELD(QPU_M_NOP, QPU_OP_MUL);
|
||||
inst |= QPU_SET_FIELD(QPU_W_NOP, QPU_WADDR_MUL);
|
||||
inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
qpu_a_dst(struct qpu_reg dst)
|
||||
{
|
||||
uint64_t inst = 0;
|
||||
|
||||
if (dst.mux <= QPU_MUX_R5) {
|
||||
/* Translate the mux to the ACCn values. */
|
||||
inst |= QPU_SET_FIELD(32 + dst.mux, QPU_WADDR_ADD);
|
||||
} else {
|
||||
inst |= QPU_SET_FIELD(dst.addr, QPU_WADDR_ADD);
|
||||
if (dst.mux == QPU_MUX_B)
|
||||
inst |= QPU_WS;
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
qpu_m_dst(struct qpu_reg dst)
|
||||
{
|
||||
uint64_t inst = 0;
|
||||
|
||||
if (dst.mux <= QPU_MUX_R5) {
|
||||
/* Translate the mux to the ACCn values. */
|
||||
inst |= QPU_SET_FIELD(32 + dst.mux, QPU_WADDR_MUL);
|
||||
} else {
|
||||
inst |= QPU_SET_FIELD(dst.addr, QPU_WADDR_MUL);
|
||||
if (dst.mux == QPU_MUX_A)
|
||||
inst |= QPU_WS;
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
qpu_a_MOV(struct qpu_reg dst, struct qpu_reg src)
|
||||
{
|
||||
uint64_t inst = 0;
|
||||
|
||||
inst |= QPU_SET_FIELD(QPU_A_OR, QPU_OP_ADD);
|
||||
inst |= qpu_a_dst(dst);
|
||||
inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_ADD);
|
||||
inst |= QPU_SET_FIELD(src.mux, QPU_ADD_A);
|
||||
inst |= QPU_SET_FIELD(src.mux, QPU_ADD_B);
|
||||
inst |= set_src_raddr(inst, src);
|
||||
inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
qpu_m_MOV(struct qpu_reg dst, struct qpu_reg src)
|
||||
{
|
||||
uint64_t inst = 0;
|
||||
|
||||
inst |= QPU_SET_FIELD(QPU_M_V8MIN, QPU_OP_MUL);
|
||||
inst |= qpu_m_dst(dst);
|
||||
inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_MUL);
|
||||
inst |= QPU_SET_FIELD(src.mux, QPU_MUL_A);
|
||||
inst |= QPU_SET_FIELD(src.mux, QPU_MUL_B);
|
||||
inst |= set_src_raddr(inst, src);
|
||||
inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
qpu_load_imm_ui(struct qpu_reg dst, uint32_t val)
|
||||
{
|
||||
uint64_t inst = 0;
|
||||
|
||||
inst |= qpu_a_dst(dst);
|
||||
inst |= qpu_m_dst(qpu_rb(QPU_W_NOP));
|
||||
inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_ADD);
|
||||
inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_MUL);
|
||||
inst |= QPU_SET_FIELD(QPU_SIG_LOAD_IMM, QPU_SIG);
|
||||
inst |= val;
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
qpu_a_alu2(enum qpu_op_add op,
|
||||
struct qpu_reg dst, struct qpu_reg src0, struct qpu_reg src1)
|
||||
{
|
||||
uint64_t inst = 0;
|
||||
|
||||
inst |= QPU_SET_FIELD(op, QPU_OP_ADD);
|
||||
inst |= qpu_a_dst(dst);
|
||||
inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_ADD);
|
||||
inst |= QPU_SET_FIELD(src0.mux, QPU_ADD_A);
|
||||
inst |= set_src_raddr(inst, src0);
|
||||
inst |= QPU_SET_FIELD(src1.mux, QPU_ADD_B);
|
||||
inst |= set_src_raddr(inst, src1);
|
||||
inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
qpu_m_alu2(enum qpu_op_mul op,
|
||||
struct qpu_reg dst, struct qpu_reg src0, struct qpu_reg src1)
|
||||
{
|
||||
uint64_t inst = 0;
|
||||
|
||||
set_src_raddr(inst, src0);
|
||||
set_src_raddr(inst, src1);
|
||||
|
||||
inst |= QPU_SET_FIELD(op, QPU_OP_MUL);
|
||||
inst |= qpu_m_dst(dst);
|
||||
inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_MUL);
|
||||
inst |= QPU_SET_FIELD(src0.mux, QPU_MUL_A);
|
||||
inst |= set_src_raddr(inst, src0);
|
||||
inst |= QPU_SET_FIELD(src1.mux, QPU_MUL_B);
|
||||
inst |= set_src_raddr(inst, src1);
|
||||
inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
qpu_inst(uint64_t add, uint64_t mul)
|
||||
{
|
||||
uint64_t merge = add | mul;
|
||||
|
||||
/* If either one has no signal field, then use the other's signal field.
|
||||
* (since QPU_SIG_NONE != 0).
|
||||
*/
|
||||
if (QPU_GET_FIELD(add, QPU_SIG) == QPU_SIG_NONE)
|
||||
merge = (merge & ~QPU_SIG_MASK) | (mul & QPU_SIG_MASK);
|
||||
else if (QPU_GET_FIELD(mul, QPU_SIG) == QPU_SIG_NONE)
|
||||
merge = (merge & ~QPU_SIG_MASK) | (add & QPU_SIG_MASK);
|
||||
else {
|
||||
assert(QPU_GET_FIELD(add, QPU_SIG) ==
|
||||
QPU_GET_FIELD(mul, QPU_SIG));
|
||||
}
|
||||
|
||||
return merge;
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef VC4_QPU_H
|
||||
#define VC4_QPU_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "vc4_qpu_defines.h"
|
||||
|
||||
struct qpu_reg {
|
||||
enum qpu_mux mux;
|
||||
uint8_t addr;
|
||||
};
|
||||
|
||||
static inline struct qpu_reg
|
||||
qpu_rn(int n)
|
||||
{
|
||||
struct qpu_reg r = {
|
||||
QPU_MUX_R0 + n,
|
||||
0,
|
||||
};
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline struct qpu_reg
|
||||
qpu_ra(int addr)
|
||||
{
|
||||
struct qpu_reg r = {
|
||||
QPU_MUX_A,
|
||||
addr,
|
||||
};
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline struct qpu_reg
|
||||
qpu_rb(int addr)
|
||||
{
|
||||
struct qpu_reg r = {
|
||||
QPU_MUX_B,
|
||||
addr,
|
||||
};
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline struct qpu_reg
|
||||
qpu_vary()
|
||||
{
|
||||
struct qpu_reg r = {
|
||||
QPU_MUX_A,
|
||||
QPU_R_VARY,
|
||||
};
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline struct qpu_reg
|
||||
qpu_unif()
|
||||
{
|
||||
struct qpu_reg r = {
|
||||
QPU_MUX_A,
|
||||
QPU_R_UNIF,
|
||||
};
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline struct qpu_reg
|
||||
qpu_vrsetup()
|
||||
{
|
||||
return qpu_ra(QPU_W_VPMVCD_SETUP);
|
||||
}
|
||||
|
||||
static inline struct qpu_reg
|
||||
qpu_vwsetup()
|
||||
{
|
||||
return qpu_rb(QPU_W_VPMVCD_SETUP);
|
||||
}
|
||||
|
||||
static inline struct qpu_reg
|
||||
qpu_tlbc()
|
||||
{
|
||||
struct qpu_reg r = {
|
||||
QPU_MUX_A,
|
||||
QPU_W_TLB_COLOR_ALL,
|
||||
};
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline struct qpu_reg qpu_r0(void) { return qpu_rn(0); }
|
||||
static inline struct qpu_reg qpu_r1(void) { return qpu_rn(1); }
|
||||
static inline struct qpu_reg qpu_r2(void) { return qpu_rn(2); }
|
||||
static inline struct qpu_reg qpu_r3(void) { return qpu_rn(3); }
|
||||
static inline struct qpu_reg qpu_r4(void) { return qpu_rn(4); }
|
||||
static inline struct qpu_reg qpu_r5(void) { return qpu_rn(5); }
|
||||
|
||||
uint64_t qpu_a_MOV(struct qpu_reg dst, struct qpu_reg src);
|
||||
uint64_t qpu_m_MOV(struct qpu_reg dst, struct qpu_reg src);
|
||||
uint64_t qpu_a_NOP(void);
|
||||
uint64_t qpu_m_NOP(void);
|
||||
uint64_t qpu_a_alu2(enum qpu_op_add op, struct qpu_reg dst,
|
||||
struct qpu_reg src0, struct qpu_reg src1);
|
||||
uint64_t qpu_m_alu2(enum qpu_op_mul op, struct qpu_reg dst,
|
||||
struct qpu_reg src0, struct qpu_reg src1);
|
||||
uint64_t qpu_inst(uint64_t add, uint64_t mul);
|
||||
uint64_t qpu_load_imm_ui(struct qpu_reg dst, uint32_t val);
|
||||
|
||||
static inline uint64_t
|
||||
qpu_load_imm_f(struct qpu_reg dst, float val)
|
||||
{
|
||||
return qpu_load_imm_ui(dst, fui(val));
|
||||
}
|
||||
|
||||
#define A_ALU2(op) \
|
||||
static inline uint64_t \
|
||||
qpu_a_##op(struct qpu_reg dst, struct qpu_reg src0, struct qpu_reg src1) \
|
||||
{ \
|
||||
return qpu_a_alu2(QPU_A_##op, dst, src0, src1); \
|
||||
}
|
||||
|
||||
#define M_ALU2(op) \
|
||||
static inline uint64_t \
|
||||
qpu_m_##op(struct qpu_reg dst, struct qpu_reg src0, struct qpu_reg src1) \
|
||||
{ \
|
||||
return qpu_m_alu2(QPU_M_##op, dst, src0, src1); \
|
||||
}
|
||||
|
||||
#define A_ALU1(op) \
|
||||
static inline uint64_t \
|
||||
qpu_a_##op(struct qpu_reg dst, struct qpu_reg src0) \
|
||||
{ \
|
||||
return qpu_a_alu2(QPU_A_##op, dst, src0, src0); \
|
||||
}
|
||||
|
||||
/*A_ALU2(NOP) */
|
||||
A_ALU2(FADD)
|
||||
A_ALU2(FSUB)
|
||||
A_ALU2(FMIN)
|
||||
A_ALU2(FMAX)
|
||||
A_ALU2(MINABS)
|
||||
A_ALU2(MAXABS)
|
||||
A_ALU1(FTOI)
|
||||
A_ALU1(ITOF)
|
||||
A_ALU2(ADD)
|
||||
A_ALU2(SUB)
|
||||
A_ALU2(SHR)
|
||||
A_ALU2(ASR)
|
||||
A_ALU2(ROR)
|
||||
A_ALU2(SHL)
|
||||
A_ALU2(MIN)
|
||||
A_ALU2(MAX)
|
||||
A_ALU2(AND)
|
||||
A_ALU2(OR)
|
||||
A_ALU2(XOR)
|
||||
A_ALU1(NOT)
|
||||
A_ALU1(CLZ)
|
||||
A_ALU2(V8ADDS)
|
||||
A_ALU2(V8SUBS)
|
||||
|
||||
/* M_ALU2(NOP) */
|
||||
M_ALU2(FMUL)
|
||||
M_ALU2(MUL24)
|
||||
M_ALU2(V8MULD)
|
||||
M_ALU2(V8MIN)
|
||||
M_ALU2(V8MAX)
|
||||
M_ALU2(V8ADDS)
|
||||
M_ALU2(V8SUBS)
|
||||
|
||||
void
|
||||
vc4_qpu_disasm(const uint64_t *instructions, int num_instructions);
|
||||
|
||||
void
|
||||
vc4_qpu_validate(uint64_t *insts, uint32_t num_inst);
|
||||
|
||||
#endif /* VC4_QPU_H */
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef VC4_QPU_DEFINES_H
|
||||
#define VC4_QPU_DEFINES_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
enum qpu_op_add {
|
||||
QPU_A_NOP,
|
||||
QPU_A_FADD,
|
||||
QPU_A_FSUB,
|
||||
QPU_A_FMIN,
|
||||
QPU_A_FMAX,
|
||||
QPU_A_MINABS,
|
||||
QPU_A_MAXABS,
|
||||
QPU_A_FTOI,
|
||||
QPU_A_ITOF,
|
||||
QPU_A_ADD = 12,
|
||||
QPU_A_SUB,
|
||||
QPU_A_SHR,
|
||||
QPU_A_ASR,
|
||||
QPU_A_ROR,
|
||||
QPU_A_SHL,
|
||||
QPU_A_MIN,
|
||||
QPU_A_MAX,
|
||||
QPU_A_AND,
|
||||
QPU_A_OR,
|
||||
QPU_A_XOR,
|
||||
QPU_A_NOT,
|
||||
QPU_A_CLZ,
|
||||
QPU_A_V8ADDS = 30,
|
||||
QPU_A_V8SUBS = 31,
|
||||
};
|
||||
|
||||
enum qpu_op_mul {
|
||||
QPU_M_NOP,
|
||||
QPU_M_FMUL,
|
||||
QPU_M_MUL24,
|
||||
QPU_M_V8MULD,
|
||||
QPU_M_V8MIN,
|
||||
QPU_M_V8MAX,
|
||||
QPU_M_V8ADDS,
|
||||
QPU_M_V8SUBS,
|
||||
};
|
||||
|
||||
enum qpu_raddr {
|
||||
/* 0-31 are the plain regfile a or b fields */
|
||||
QPU_R_UNIF = 32,
|
||||
QPU_R_VARY = 35,
|
||||
QPU_R_ELEM_QPU = 38,
|
||||
QPU_R_NOP,
|
||||
QPU_R_XY_PIXEL_COORD = 41,
|
||||
QPU_R_MS_REV_FLAGS = 41,
|
||||
QPU_R_VPM = 48,
|
||||
QPU_R_VPM_LD_BUSY,
|
||||
QPU_R_VPM_LD_WAIT,
|
||||
QPU_R_MUTEX_ACQUIRE,
|
||||
};
|
||||
|
||||
enum qpu_waddr {
|
||||
/* 0-31 are the plain regfile a or b fields */
|
||||
QPU_W_ACC0 = 32, /* aka r0 */
|
||||
QPU_W_ACC1,
|
||||
QPU_W_ACC2,
|
||||
QPU_W_ACC3,
|
||||
QPU_W_TMU_NOSWAP,
|
||||
QPU_W_ACC5,
|
||||
QPU_W_HOST_INT,
|
||||
QPU_W_NOP,
|
||||
QPU_W_UNIFORMS_ADDRESS,
|
||||
QPU_W_QUAD_XY, /* X for regfile a, Y for regfile b */
|
||||
QPU_W_MS_FLAGS = 42,
|
||||
QPU_W_REV_FLAG = 42,
|
||||
QPU_W_TLB_STENCIL_SETUP = 43,
|
||||
QPU_W_TLB_Z,
|
||||
QPU_W_TLB_COLOR_MS,
|
||||
QPU_W_TLB_COLOR_ALL,
|
||||
QPU_W_TLB_ALPHA_MASK,
|
||||
QPU_W_VPM,
|
||||
QPU_W_VPMVCD_SETUP, /* LD for regfile a, ST for regfile b */
|
||||
QPU_W_VPM_ADDR, /* LD for regfile a, ST for regfile b */
|
||||
QPU_W_MUTEX_RELEASE,
|
||||
QPU_W_SFU_RECIP,
|
||||
QPU_W_SFU_RECIPSQRT,
|
||||
QPU_W_SFU_EXP,
|
||||
QPU_W_SFU_LOG,
|
||||
QPU_W_TMU0_S,
|
||||
QPU_W_TMU0_T,
|
||||
QPU_W_TMU0_R,
|
||||
QPU_W_TMU0_B,
|
||||
QPU_W_TMU1_S,
|
||||
QPU_W_TMU1_T,
|
||||
QPU_W_TMU1_R,
|
||||
QPU_W_TMU1_B,
|
||||
};
|
||||
|
||||
enum qpu_sig_bits {
|
||||
QPU_SIG_SW_BREAKPOINT,
|
||||
QPU_SIG_NONE,
|
||||
QPU_SIG_THREAD_SWITCH,
|
||||
QPU_SIG_PROG_END,
|
||||
QPU_SIG_WAIT_FOR_SCOREBOARD,
|
||||
QPU_SIG_SCOREBOARD_UNLOCK,
|
||||
QPU_SIG_LAST_THREAD_SWITCH,
|
||||
QPU_SIG_COVERAGE_LOAD,
|
||||
QPU_SIG_COLOR_LOAD,
|
||||
QPU_SIG_COLOR_LOAD_END,
|
||||
QPU_SIG_LOAD_TMU0,
|
||||
QPU_SIG_LOAD_TMU1,
|
||||
QPU_SIG_ALPHA_MASK_LOAD,
|
||||
QPU_SIG_SMALL_IMM,
|
||||
QPU_SIG_LOAD_IMM,
|
||||
QPU_SIG_BRANCH
|
||||
};
|
||||
|
||||
enum qpu_mux {
|
||||
/* hardware mux values */
|
||||
QPU_MUX_R0,
|
||||
QPU_MUX_R1,
|
||||
QPU_MUX_R2,
|
||||
QPU_MUX_R3,
|
||||
QPU_MUX_R4,
|
||||
QPU_MUX_R5,
|
||||
QPU_MUX_A,
|
||||
QPU_MUX_B,
|
||||
|
||||
/* non-hardware mux values */
|
||||
QPU_MUX_IMM,
|
||||
};
|
||||
|
||||
enum qpu_cond {
|
||||
QPU_COND_NEVER,
|
||||
QPU_COND_ALWAYS,
|
||||
QPU_COND_ZS,
|
||||
QPU_COND_ZC,
|
||||
QPU_COND_NS,
|
||||
QPU_COND_NC,
|
||||
QPU_COND_CS,
|
||||
QPU_COND_CC,
|
||||
};
|
||||
|
||||
enum qpu_pack_mul {
|
||||
QPU_PACK_MUL_NOP,
|
||||
QPU_PACK_MUL_8888 = 3, /* replicated to each 8 bits of the 32-bit dst. */
|
||||
QPU_PACK_MUL_8A,
|
||||
QPU_PACK_MUL_8B,
|
||||
QPU_PACK_MUL_8C,
|
||||
QPU_PACK_MUL_8D,
|
||||
};
|
||||
|
||||
enum qpu_pack_a {
|
||||
QPU_PACK_A_NOP,
|
||||
/* convert to 16 bit float if float input, or to int16. */
|
||||
QPU_PACK_A_16A,
|
||||
QPU_PACK_A_16B,
|
||||
/* replicated to each 8 bits of the 32-bit dst. */
|
||||
QPU_PACK_A_8888,
|
||||
/* Convert to 8-bit unsigned int. */
|
||||
QPU_PACK_A_8A,
|
||||
QPU_PACK_A_8B,
|
||||
QPU_PACK_A_8C,
|
||||
QPU_PACK_A_8D,
|
||||
|
||||
/* Saturating variants of the previous instructions. */
|
||||
QPU_PACK_A_32_SAT, /* int-only */
|
||||
QPU_PACK_A_16A_SAT, /* int or float */
|
||||
QPU_PACK_A_16B_SAT,
|
||||
QPU_PACK_A_8888_SAT,
|
||||
QPU_PACK_A_8A_SAT,
|
||||
QPU_PACK_A_8B_SAT,
|
||||
QPU_PACK_A_8C_SAT,
|
||||
QPU_PACK_A_8D_SAT,
|
||||
};
|
||||
|
||||
#define QPU_MASK(high, low) ((((uint64_t)1<<((high)-(low)+1))-1)<<(low))
|
||||
/* Using the GNU statement expression extension */
|
||||
#define QPU_SET_FIELD(value, field) \
|
||||
({ \
|
||||
uint64_t fieldval = (uint64_t)(value) << field ## _SHIFT; \
|
||||
assert((fieldval & ~ field ## _MASK) == 0); \
|
||||
fieldval & field ## _MASK; \
|
||||
})
|
||||
|
||||
#define QPU_GET_FIELD(word, field) ((uint32_t)(((word) & field ## _MASK) >> field ## _SHIFT))
|
||||
|
||||
#define QPU_SIG_SHIFT 60
|
||||
#define QPU_SIG_MASK QPU_MASK(63, 60)
|
||||
|
||||
/**
|
||||
* If set, the pack field means PACK_MUL or R4 packing, instead of normal
|
||||
* regfile a packing.
|
||||
*/
|
||||
#define QPU_PM ((uint64_t)1 << 56)
|
||||
|
||||
#define QPU_PACK_SHIFT 52
|
||||
#define QPU_PACK_MASK QPU_MASK(55, 52)
|
||||
|
||||
#define QPU_COND_ADD_SHIFT 49
|
||||
#define QPU_COND_ADD_MASK QPU_MASK(51, 49)
|
||||
#define QPU_COND_MUL_SHIFT 46
|
||||
#define QPU_COND_MUL_MASK QPU_MASK(48, 46)
|
||||
|
||||
#define QPU_WADDR_ADD_SHIFT 38
|
||||
#define QPU_WADDR_ADD_MASK QPU_MASK(43, 38)
|
||||
#define QPU_WADDR_MUL_SHIFT 32
|
||||
#define QPU_WADDR_MUL_MASK QPU_MASK(37, 32)
|
||||
|
||||
#define QPU_OP_MUL_SHIFT 29
|
||||
#define QPU_OP_MUL_MASK QPU_MASK(31, 29)
|
||||
|
||||
#define QPU_RADDR_A_SHIFT 18
|
||||
#define QPU_RADDR_A_MASK QPU_MASK(23, 18)
|
||||
#define QPU_RADDR_B_SHIFT 12
|
||||
#define QPU_RADDR_B_MASK QPU_MASK(17, 12)
|
||||
#define QPU_SMALL_IMM_SHIFT 12
|
||||
#define QPU_SMALL_IMM_MASK QPU_MASK(17, 12)
|
||||
|
||||
#define QPU_ADD_A_SHIFT 9
|
||||
#define QPU_ADD_A_MASK QPU_MASK(11, 9)
|
||||
#define QPU_ADD_B_SHIFT 6
|
||||
#define QPU_ADD_B_MASK QPU_MASK(8, 6)
|
||||
#define QPU_MUL_A_SHIFT 3
|
||||
#define QPU_MUL_A_MASK QPU_MASK(5, 3)
|
||||
#define QPU_MUL_B_SHIFT 0
|
||||
#define QPU_MUL_B_MASK QPU_MASK(2, 0)
|
||||
|
||||
#define QPU_WS ((uint64_t)1 << 44)
|
||||
|
||||
#define QPU_OP_ADD_SHIFT 24
|
||||
#define QPU_OP_ADD_MASK QPU_MASK(28, 24)
|
||||
|
||||
#endif /* VC4_QPU_DEFINES_H */
|
|
@ -0,0 +1,363 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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 <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vc4_qpu.h"
|
||||
#include "vc4_qpu_defines.h"
|
||||
|
||||
static const char *qpu_add_opcodes[] = {
|
||||
[QPU_A_NOP] = "nop",
|
||||
[QPU_A_FADD] = "fadd",
|
||||
[QPU_A_FSUB] = "fsub",
|
||||
[QPU_A_FMIN] = "fmin",
|
||||
[QPU_A_FMAX] = "fmax",
|
||||
[QPU_A_MINABS] = "minabs",
|
||||
[QPU_A_MAXABS] = "maxabs",
|
||||
[QPU_A_FTOI] = "ftoi",
|
||||
[QPU_A_ITOF] = "itof",
|
||||
[QPU_A_ADD] = "add",
|
||||
[QPU_A_SUB] = "sub",
|
||||
[QPU_A_SHR] = "shr",
|
||||
[QPU_A_ASR] = "asr",
|
||||
[QPU_A_ROR] = "ror",
|
||||
[QPU_A_SHL] = "shl",
|
||||
[QPU_A_MIN] = "min",
|
||||
[QPU_A_MAX] = "max",
|
||||
[QPU_A_AND] = "and",
|
||||
[QPU_A_OR] = "or",
|
||||
[QPU_A_XOR] = "xor",
|
||||
[QPU_A_NOT] = "not",
|
||||
[QPU_A_CLZ] = "clz",
|
||||
[QPU_A_V8ADDS] = "v8adds",
|
||||
[QPU_A_V8SUBS] = "v8subs",
|
||||
};
|
||||
|
||||
static const char *qpu_mul_opcodes[] = {
|
||||
[QPU_M_NOP] = "nop",
|
||||
[QPU_M_FMUL] = "fmul",
|
||||
[QPU_M_MUL24] = "mul24",
|
||||
[QPU_M_V8MULD] = "v8muld",
|
||||
[QPU_M_V8MIN] = "v8min",
|
||||
[QPU_M_V8MAX] = "v8max",
|
||||
[QPU_M_V8ADDS] = "v8adds",
|
||||
[QPU_M_V8SUBS] = "v8subs",
|
||||
};
|
||||
|
||||
static const char *qpu_sig[] = {
|
||||
[QPU_SIG_SW_BREAKPOINT] = "sig_brk",
|
||||
[QPU_SIG_NONE] = "",
|
||||
[QPU_SIG_THREAD_SWITCH] = "sig_switch",
|
||||
[QPU_SIG_PROG_END] = "sig_end",
|
||||
[QPU_SIG_WAIT_FOR_SCOREBOARD] = "sig_wait_score",
|
||||
[QPU_SIG_SCOREBOARD_UNLOCK] = "sig_unlock_score",
|
||||
[QPU_SIG_LAST_THREAD_SWITCH] = "sig_thread_switch",
|
||||
[QPU_SIG_COVERAGE_LOAD] = "sig_coverage_load",
|
||||
[QPU_SIG_COLOR_LOAD] = "sig_color_load",
|
||||
[QPU_SIG_COLOR_LOAD_END] = "sig_color_load_end",
|
||||
[QPU_SIG_LOAD_TMU0] = "load_tmu0",
|
||||
[QPU_SIG_LOAD_TMU1] = "load_tmu1",
|
||||
[QPU_SIG_ALPHA_MASK_LOAD] = "sig_alpha_mask_load",
|
||||
[QPU_SIG_SMALL_IMM] = "sig_small_imm",
|
||||
[QPU_SIG_LOAD_IMM] = "sig_load_imm",
|
||||
[QPU_SIG_BRANCH] = "sig_branch",
|
||||
};
|
||||
|
||||
static const char *qpu_pack_mul[] = {
|
||||
[QPU_PACK_MUL_NOP] = "",
|
||||
[QPU_PACK_MUL_8888] = "8888",
|
||||
[QPU_PACK_MUL_8A] = "8a",
|
||||
[QPU_PACK_MUL_8B] = "8b",
|
||||
[QPU_PACK_MUL_8C] = "8c",
|
||||
[QPU_PACK_MUL_8D] = "8d",
|
||||
};
|
||||
|
||||
static const char *special_read_a[] = {
|
||||
"uni",
|
||||
NULL,
|
||||
NULL,
|
||||
"vary",
|
||||
NULL,
|
||||
NULL,
|
||||
"elem",
|
||||
"nop",
|
||||
NULL,
|
||||
"x_pix",
|
||||
"ms_flags",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
"vpm_read",
|
||||
"vpm_ld_busy",
|
||||
"vpm_ld_wait",
|
||||
"mutex_acq"
|
||||
};
|
||||
|
||||
static const char *special_read_b[] = {
|
||||
"uni",
|
||||
NULL,
|
||||
NULL,
|
||||
"vary",
|
||||
NULL,
|
||||
NULL,
|
||||
"qpu",
|
||||
"nop",
|
||||
NULL,
|
||||
"y_pix",
|
||||
"rev_flag",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
"vpm_read",
|
||||
"vpm_st_busy",
|
||||
"vpm_st_wait",
|
||||
"mutex_acq"
|
||||
};
|
||||
|
||||
/**
|
||||
* This has the B-file descriptions for register writes.
|
||||
*
|
||||
* Since only a couple of regs are different between A and B, the A overrides
|
||||
* are in get_special_write_desc().
|
||||
*/
|
||||
static const char *special_write[] = {
|
||||
[QPU_W_ACC0] = "r0",
|
||||
[QPU_W_ACC1] = "r1",
|
||||
[QPU_W_ACC2] = "r2",
|
||||
[QPU_W_ACC3] = "r3",
|
||||
[QPU_W_TMU_NOSWAP] = "tmu_noswap",
|
||||
[QPU_W_ACC5] = "r5",
|
||||
[QPU_W_HOST_INT] = "host_int",
|
||||
[QPU_W_NOP] = "nop",
|
||||
[QPU_W_UNIFORMS_ADDRESS] = "uniforms_addr",
|
||||
[QPU_W_QUAD_XY] = "quad_y",
|
||||
[QPU_W_MS_FLAGS] = "ms_flags",
|
||||
[QPU_W_TLB_STENCIL_SETUP] = "tlb_stencil_setup",
|
||||
[QPU_W_TLB_Z] = "tlb_z",
|
||||
[QPU_W_TLB_COLOR_MS] = "tlb_color_ms",
|
||||
[QPU_W_TLB_COLOR_ALL] = "tlb_color_all",
|
||||
[QPU_W_VPM] = "vpm",
|
||||
[QPU_W_VPMVCD_SETUP] = "vw_setup",
|
||||
[QPU_W_VPM_ADDR] = "vw_addr",
|
||||
[QPU_W_MUTEX_RELEASE] = "mutex_release",
|
||||
[QPU_W_SFU_RECIP] = "sfu_recip",
|
||||
[QPU_W_SFU_RECIPSQRT] = "sfu_recipsqrt",
|
||||
[QPU_W_SFU_EXP] = "sfu_exp",
|
||||
[QPU_W_SFU_LOG] = "sfu_log",
|
||||
[QPU_W_TMU0_S] = "tmu0_s",
|
||||
[QPU_W_TMU0_T] = "tmu0_t",
|
||||
[QPU_W_TMU0_R] = "tmu0_r",
|
||||
[QPU_W_TMU0_B] = "tmu0_b",
|
||||
[QPU_W_TMU1_S] = "tmu1_s",
|
||||
[QPU_W_TMU1_T] = "tmu1_t",
|
||||
[QPU_W_TMU1_R] = "tmu1_r",
|
||||
[QPU_W_TMU1_B] = "tmu1_b",
|
||||
};
|
||||
|
||||
static const char *qpu_pack_a[] = {
|
||||
[QPU_PACK_A_NOP] = "",
|
||||
[QPU_PACK_A_16A] = ".16a",
|
||||
[QPU_PACK_A_16B] = ".16b",
|
||||
[QPU_PACK_A_8888] = ".8888",
|
||||
[QPU_PACK_A_8A] = ".8a",
|
||||
[QPU_PACK_A_8B] = ".8b",
|
||||
[QPU_PACK_A_8C] = ".8c",
|
||||
[QPU_PACK_A_8D] = ".8d",
|
||||
|
||||
[QPU_PACK_A_32_SAT] = ".sat",
|
||||
[QPU_PACK_A_16A_SAT] = ".16a.sat",
|
||||
[QPU_PACK_A_16B_SAT] = ".16b.sat",
|
||||
[QPU_PACK_A_8888_SAT] = ".8888.sat",
|
||||
[QPU_PACK_A_8A_SAT] = ".8a.sat",
|
||||
[QPU_PACK_A_8B_SAT] = ".8b.sat",
|
||||
[QPU_PACK_A_8C_SAT] = ".8c.sat",
|
||||
[QPU_PACK_A_8D_SAT] = ".8d.sat",
|
||||
};
|
||||
|
||||
#define DESC(array, index) \
|
||||
((index > ARRAY_SIZE(array) || !(array)[index]) ? \
|
||||
"???" : (array)[index])
|
||||
|
||||
static const char *
|
||||
get_special_write_desc(int reg, bool is_a)
|
||||
{
|
||||
if (is_a) {
|
||||
switch (reg) {
|
||||
case QPU_W_QUAD_XY:
|
||||
return "quad_x";
|
||||
case QPU_W_VPMVCD_SETUP:
|
||||
return "vr_setup";
|
||||
case QPU_W_VPM_ADDR:
|
||||
return "vr_addr";
|
||||
}
|
||||
}
|
||||
|
||||
return special_write[reg];
|
||||
}
|
||||
|
||||
static void
|
||||
print_alu_dst(uint64_t inst, bool is_mul)
|
||||
{
|
||||
bool is_a = is_mul == ((inst & QPU_WS) != 0);
|
||||
uint32_t waddr = (is_mul ?
|
||||
QPU_GET_FIELD(inst, QPU_WADDR_MUL) :
|
||||
QPU_GET_FIELD(inst, QPU_WADDR_ADD));
|
||||
const char *file = is_a ? "a" : "b";
|
||||
uint32_t pack = QPU_GET_FIELD(inst, QPU_PACK);
|
||||
|
||||
if (waddr <= 31)
|
||||
fprintf(stderr, "r%s%d", file, waddr);
|
||||
else if (get_special_write_desc(waddr, is_a))
|
||||
fprintf(stderr, "%s", get_special_write_desc(waddr, is_a));
|
||||
else
|
||||
fprintf(stderr, "%s%d?", file, waddr);
|
||||
|
||||
if (is_mul && (inst & QPU_PM)) {
|
||||
fprintf(stderr, ".%s", DESC(qpu_pack_mul, pack));
|
||||
} else if (is_a && !(inst & QPU_PM)) {
|
||||
fprintf(stderr, "%s", DESC(qpu_pack_a, pack));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_alu_src(uint64_t inst, uint32_t mux)
|
||||
{
|
||||
bool is_a = mux != QPU_MUX_B;
|
||||
const char *file = is_a ? "a" : "b";
|
||||
uint32_t raddr = (is_a ?
|
||||
QPU_GET_FIELD(inst, QPU_RADDR_A) :
|
||||
QPU_GET_FIELD(inst, QPU_RADDR_B));
|
||||
|
||||
if (mux <= QPU_MUX_R5)
|
||||
fprintf(stderr, "r%d", mux);
|
||||
else if (!is_a &&
|
||||
QPU_GET_FIELD(inst, QPU_SIG) == QPU_SIG_SMALL_IMM) {
|
||||
uint32_t si = QPU_GET_FIELD(inst, QPU_SMALL_IMM);
|
||||
if (si <= 15)
|
||||
fprintf(stderr, "%d", si);
|
||||
else if (si <= 31)
|
||||
fprintf(stderr, "%d", -16 + (si - 16));
|
||||
else if (si <= 39)
|
||||
fprintf(stderr, "%.1f", (float)(1 << (si - 32)));
|
||||
else if (si <= 47)
|
||||
fprintf(stderr, "%f", 1.0f / (256 / (si - 39)));
|
||||
else
|
||||
fprintf(stderr, "???");
|
||||
} else if (raddr <= 31)
|
||||
fprintf(stderr, "r%s%d", file, raddr);
|
||||
else {
|
||||
if (is_a)
|
||||
fprintf(stderr, "%s", DESC(special_read_a, raddr - 32));
|
||||
else
|
||||
fprintf(stderr, "%s", DESC(special_read_b, raddr - 32));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_add_op(uint64_t inst)
|
||||
{
|
||||
uint32_t op_add = QPU_GET_FIELD(inst, QPU_OP_ADD);
|
||||
bool is_mov = (op_add == QPU_A_OR &&
|
||||
QPU_GET_FIELD(inst, QPU_ADD_A) ==
|
||||
QPU_GET_FIELD(inst, QPU_ADD_B));
|
||||
|
||||
fprintf(stderr, "%s ", is_mov ? "mov" : DESC(qpu_add_opcodes, op_add));
|
||||
|
||||
print_alu_dst(inst, false);
|
||||
fprintf(stderr, ", ");
|
||||
|
||||
print_alu_src(inst, QPU_GET_FIELD(inst, QPU_ADD_A));
|
||||
|
||||
if (!is_mov) {
|
||||
fprintf(stderr, ", ");
|
||||
|
||||
print_alu_src(inst, QPU_GET_FIELD(inst, QPU_ADD_B));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_mul_op(uint64_t inst)
|
||||
{
|
||||
uint32_t op_mul = QPU_GET_FIELD(inst, QPU_OP_MUL);
|
||||
bool is_mov = (op_mul == QPU_M_V8MIN &&
|
||||
QPU_GET_FIELD(inst, QPU_MUL_A) ==
|
||||
QPU_GET_FIELD(inst, QPU_MUL_B));
|
||||
|
||||
fprintf(stderr, "%s ", is_mov ? "mov" : DESC(qpu_mul_opcodes, op_mul));
|
||||
|
||||
print_alu_dst(inst, true);
|
||||
fprintf(stderr, ", ");
|
||||
|
||||
print_alu_src(inst, QPU_GET_FIELD(inst, QPU_MUL_A));
|
||||
|
||||
if (!is_mov) {
|
||||
fprintf(stderr, ", ");
|
||||
print_alu_src(inst, QPU_GET_FIELD(inst, QPU_MUL_B));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_load_imm(uint64_t inst)
|
||||
{
|
||||
uint32_t imm = inst;
|
||||
|
||||
fprintf(stderr, "load_imm ");
|
||||
print_alu_dst(inst, false);
|
||||
fprintf(stderr, ", ");
|
||||
print_alu_dst(inst, true);
|
||||
fprintf(stderr, ", ");
|
||||
fprintf(stderr, "0x%08x (%f)", imm, uif(imm));
|
||||
}
|
||||
|
||||
void
|
||||
vc4_qpu_disasm(const uint64_t *instructions, int num_instructions)
|
||||
{
|
||||
for (int i = 0; i < num_instructions; i++) {
|
||||
uint64_t inst = instructions[i];
|
||||
uint32_t sig = QPU_GET_FIELD(inst, QPU_SIG);
|
||||
|
||||
switch (sig) {
|
||||
case QPU_SIG_BRANCH:
|
||||
fprintf(stderr, "branch\n");
|
||||
break;
|
||||
case QPU_SIG_LOAD_IMM:
|
||||
print_load_imm(inst);
|
||||
break;
|
||||
default:
|
||||
if (sig != QPU_SIG_NONE)
|
||||
fprintf(stderr, "%s ", DESC(qpu_sig, sig));
|
||||
print_add_op(inst);
|
||||
fprintf(stderr, " ; ");
|
||||
print_mul_op(inst);
|
||||
|
||||
if (num_instructions != 1)
|
||||
fprintf(stderr, "\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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 "vc4_qpu.h"
|
||||
|
||||
static bool
|
||||
writes_reg(uint64_t inst, uint32_t w)
|
||||
{
|
||||
return (QPU_GET_FIELD(inst, QPU_WADDR_ADD) == w ||
|
||||
QPU_GET_FIELD(inst, QPU_WADDR_MUL) == w);
|
||||
}
|
||||
|
||||
static bool
|
||||
_reads_reg(uint64_t inst, uint32_t r, bool ignore_a, bool ignore_b)
|
||||
{
|
||||
struct {
|
||||
uint32_t mux, addr;
|
||||
} src_regs[] = {
|
||||
{ QPU_GET_FIELD(inst, QPU_ADD_A) },
|
||||
{ QPU_GET_FIELD(inst, QPU_ADD_B) },
|
||||
{ QPU_GET_FIELD(inst, QPU_MUL_A) },
|
||||
{ QPU_GET_FIELD(inst, QPU_MUL_B) },
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(src_regs); i++) {
|
||||
if (!ignore_a &&
|
||||
src_regs[i].mux == QPU_MUX_A &&
|
||||
(QPU_GET_FIELD(inst, QPU_RADDR_A) == r))
|
||||
return true;
|
||||
|
||||
if (!ignore_b &&
|
||||
src_regs[i].mux == QPU_MUX_B &&
|
||||
(QPU_GET_FIELD(inst, QPU_RADDR_B) == r))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
reads_reg(uint64_t inst, uint32_t r)
|
||||
{
|
||||
return _reads_reg(inst, r, false, false);
|
||||
}
|
||||
|
||||
static bool
|
||||
reads_a_reg(uint64_t inst, uint32_t r)
|
||||
{
|
||||
return _reads_reg(inst, r, false, true);
|
||||
}
|
||||
|
||||
static bool
|
||||
writes_sfu(uint64_t inst)
|
||||
{
|
||||
return (writes_reg(inst, QPU_W_SFU_RECIP) ||
|
||||
writes_reg(inst, QPU_W_SFU_RECIPSQRT) ||
|
||||
writes_reg(inst, QPU_W_SFU_EXP) ||
|
||||
writes_reg(inst, QPU_W_SFU_LOG));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for the instruction restrictions from page 37 ("Summary of
|
||||
* Instruction Restrictions").
|
||||
*/
|
||||
void
|
||||
vc4_qpu_validate(uint64_t *insts, uint32_t num_inst)
|
||||
{
|
||||
for (int i = 0; i < num_inst; i++) {
|
||||
uint64_t inst = insts[i];
|
||||
|
||||
if (QPU_GET_FIELD(inst, QPU_SIG) != QPU_SIG_PROG_END)
|
||||
continue;
|
||||
|
||||
/* "The Thread End instruction must not write to either physical
|
||||
* regfile A or B."
|
||||
*/
|
||||
assert(QPU_GET_FIELD(inst, QPU_WADDR_ADD) >= 32);
|
||||
assert(QPU_GET_FIELD(inst, QPU_WADDR_MUL) >= 32);
|
||||
|
||||
/* Two delay slots will be executed. */
|
||||
assert(i + 2 <= num_inst);
|
||||
|
||||
for (int j = i; j < i + 2; j++) {
|
||||
/* "The last three instructions of any program
|
||||
* (Thread End plus the following two delay-slot
|
||||
* instructions) must not do varyings read, uniforms
|
||||
* read or any kind of VPM, VDR, or VDW read or
|
||||
* write."
|
||||
*/
|
||||
assert(!writes_reg(insts[j], QPU_W_VPM));
|
||||
assert(!reads_reg(insts[j], QPU_R_VARY));
|
||||
assert(!reads_reg(insts[j], QPU_R_UNIF));
|
||||
assert(!reads_reg(insts[j], QPU_R_VPM));
|
||||
|
||||
/* "The Thread End instruction and the following two
|
||||
* delay slot instructions must not write or read
|
||||
* address 14 in either regfile A or B."
|
||||
*/
|
||||
assert(!writes_reg(insts[j], 14));
|
||||
assert(!reads_reg(insts[j], 14));
|
||||
|
||||
}
|
||||
|
||||
/* "The final program instruction (the second delay slot
|
||||
* instruction) must not do a TLB Z write."
|
||||
*/
|
||||
assert(!writes_reg(insts[i + 2], QPU_W_TLB_Z));
|
||||
}
|
||||
|
||||
/* "A scoreboard wait must not occur in the first two instructions of
|
||||
* a fragment shader. This is either the explicit Wait for Scoreboard
|
||||
* signal or an implicit wait with the first tile-buffer read or
|
||||
* write instruction."
|
||||
*/
|
||||
for (int i = 0; i < 2; i++) {
|
||||
uint64_t inst = insts[i];
|
||||
|
||||
assert(QPU_GET_FIELD(inst, QPU_SIG) != QPU_SIG_COLOR_LOAD);
|
||||
assert(QPU_GET_FIELD(inst, QPU_SIG) !=
|
||||
QPU_SIG_WAIT_FOR_SCOREBOARD);
|
||||
assert(!writes_reg(inst, QPU_W_TLB_COLOR_MS));
|
||||
assert(!writes_reg(inst, QPU_W_TLB_COLOR_ALL));
|
||||
assert(!writes_reg(inst, QPU_W_TLB_Z));
|
||||
|
||||
}
|
||||
|
||||
/* "If TMU_NOSWAP is written, the write must be three instructions
|
||||
* before the first TMU write instruction. For example, if
|
||||
* TMU_NOSWAP is written in the first shader instruction, the first
|
||||
* TMU write cannot occur before the 4th shader instruction."
|
||||
*/
|
||||
int last_tmu_noswap = -10;
|
||||
for (int i = 0; i < num_inst; i++) {
|
||||
uint64_t inst = insts[i];
|
||||
|
||||
assert((i - last_tmu_noswap) > 3 ||
|
||||
(!writes_reg(inst, QPU_W_TMU0_S) &&
|
||||
!writes_reg(inst, QPU_W_TMU1_S)));
|
||||
|
||||
if (writes_reg(inst, QPU_W_TMU_NOSWAP))
|
||||
last_tmu_noswap = i;
|
||||
}
|
||||
|
||||
/* "An instruction must not read from a location in physical regfile A
|
||||
* or B that was written to by the previous instruction."
|
||||
*/
|
||||
for (int i = 0; i < num_inst - 1; i++) {
|
||||
uint64_t inst = insts[i];
|
||||
uint32_t add_waddr = QPU_GET_FIELD(inst, QPU_WADDR_ADD);
|
||||
uint32_t mul_waddr = QPU_GET_FIELD(inst, QPU_WADDR_ADD);
|
||||
|
||||
assert(add_waddr >= 32 || !reads_reg(insts[i + 1], add_waddr));
|
||||
assert(mul_waddr >= 32 || !reads_reg(insts[i + 1], mul_waddr));
|
||||
}
|
||||
|
||||
/* "After an SFU lookup instruction, accumulator r4 must not be read
|
||||
* in the following two instructions. Any other instruction that
|
||||
* results in r4 being written (that is, TMU read, TLB read, SFU
|
||||
* lookup) cannot occur in the two instructions following an SFU
|
||||
* lookup."
|
||||
*/
|
||||
int last_sfu_inst = -10;
|
||||
for (int i = 0; i < num_inst - 1; i++) {
|
||||
uint64_t inst = insts[i];
|
||||
|
||||
assert(i - last_sfu_inst > 2 ||
|
||||
(!writes_sfu(inst) &&
|
||||
!writes_reg(inst, QPU_W_TMU0_S) &&
|
||||
!writes_reg(inst, QPU_W_TMU1_S) &&
|
||||
QPU_GET_FIELD(inst, QPU_SIG) != QPU_SIG_COLOR_LOAD));
|
||||
|
||||
if (writes_sfu(inst))
|
||||
last_sfu_inst = i;
|
||||
}
|
||||
|
||||
int last_r5_write = -10;
|
||||
for (int i = 0; i < num_inst - 1; i++) {
|
||||
uint64_t inst = insts[i];
|
||||
|
||||
/* "An instruction that does a vector rotate by r5 must not
|
||||
* immediately follow an instruction that writes to r5."
|
||||
*/
|
||||
assert(last_r5_write != i - 1 ||
|
||||
QPU_GET_FIELD(inst, QPU_SIG) != QPU_SIG_SMALL_IMM ||
|
||||
QPU_GET_FIELD(inst, QPU_SMALL_IMM) != 48);
|
||||
}
|
||||
|
||||
/* "An instruction that does a vector rotate must not immediately
|
||||
* follow an instruction that writes to the accumulator that is being
|
||||
* rotated.
|
||||
*
|
||||
* XXX: TODO.
|
||||
*/
|
||||
|
||||
/* "After an instruction that does a TLB Z write, the multisample mask
|
||||
* must not be read as an instruction input argument in the following
|
||||
* two instruction. The TLB Z write instruction can, however, be
|
||||
* followed immediately by a TLB color write."
|
||||
*/
|
||||
for (int i = 0; i < num_inst - 1; i++) {
|
||||
uint64_t inst = insts[i];
|
||||
if (writes_reg(inst, QPU_W_TLB_Z)) {
|
||||
assert(!reads_a_reg(insts[i + 1], QPU_R_MS_REV_FLAGS));
|
||||
assert(!reads_a_reg(insts[i + 2], QPU_R_MS_REV_FLAGS));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "A single instruction can only perform a maximum of one of the
|
||||
* following closely coupled peripheral accesses in a single
|
||||
* instruction: TMU write, TMU read, TLB write, TLB read, TLB
|
||||
* combined color read and write, SFU write, Mutex read or Semaphore
|
||||
* access."
|
||||
*/
|
||||
for (int i = 0; i < num_inst - 1; i++) {
|
||||
uint64_t inst = insts[i];
|
||||
int accesses = 0;
|
||||
static const uint32_t specials[] = {
|
||||
QPU_W_TLB_COLOR_MS,
|
||||
QPU_W_TLB_COLOR_ALL,
|
||||
QPU_W_TLB_Z,
|
||||
QPU_W_TMU0_S,
|
||||
QPU_W_TMU0_T,
|
||||
QPU_W_TMU0_R,
|
||||
QPU_W_TMU0_B,
|
||||
QPU_W_TMU1_S,
|
||||
QPU_W_TMU1_T,
|
||||
QPU_W_TMU1_R,
|
||||
QPU_W_TMU1_B,
|
||||
QPU_W_SFU_RECIP,
|
||||
QPU_W_SFU_RECIPSQRT,
|
||||
QPU_W_SFU_EXP,
|
||||
QPU_W_SFU_LOG,
|
||||
};
|
||||
|
||||
for (int j = 0; j < ARRAY_SIZE(specials); j++) {
|
||||
if (writes_reg(inst, specials[j]))
|
||||
accesses++;
|
||||
}
|
||||
|
||||
if (reads_reg(inst, QPU_R_MUTEX_ACQUIRE))
|
||||
accesses++;
|
||||
|
||||
/* XXX: semaphore, combined color read/write? */
|
||||
switch (QPU_GET_FIELD(inst, QPU_SIG)) {
|
||||
case QPU_SIG_COLOR_LOAD:
|
||||
case QPU_SIG_COLOR_LOAD_END:
|
||||
case QPU_SIG_LOAD_TMU0:
|
||||
case QPU_SIG_LOAD_TMU1:
|
||||
accesses++;
|
||||
}
|
||||
|
||||
assert(accesses <= 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
|
||||
*
|
||||
* 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 "util/u_memory.h"
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_surface.h"
|
||||
#include "util/u_blitter.h"
|
||||
|
||||
#include "vc4_screen.h"
|
||||
#include "vc4_context.h"
|
||||
#include "vc4_resource.h"
|
||||
|
||||
static void
|
||||
vc4_resource_transfer_unmap(struct pipe_context *pctx,
|
||||
struct pipe_transfer *ptrans)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
|
||||
pipe_resource_reference(&ptrans->resource, NULL);
|
||||
util_slab_free(&vc4->transfer_pool, ptrans);
|
||||
}
|
||||
|
||||
static void *
|
||||
vc4_resource_transfer_map(struct pipe_context *pctx,
|
||||
struct pipe_resource *prsc,
|
||||
unsigned level, unsigned usage,
|
||||
const struct pipe_box *box,
|
||||
struct pipe_transfer **pptrans)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
struct vc4_resource *rsc = vc4_resource(prsc);
|
||||
struct pipe_transfer *ptrans;
|
||||
enum pipe_format format = prsc->format;
|
||||
char *buf;
|
||||
|
||||
ptrans = util_slab_alloc(&vc4->transfer_pool);
|
||||
if (!ptrans)
|
||||
return NULL;
|
||||
|
||||
/* util_slab_alloc() doesn't zero: */
|
||||
memset(ptrans, 0, sizeof(*ptrans));
|
||||
|
||||
pipe_resource_reference(&ptrans->resource, prsc);
|
||||
ptrans->level = level;
|
||||
ptrans->usage = usage;
|
||||
ptrans->box = *box;
|
||||
ptrans->stride = rsc->slices[level].stride;
|
||||
ptrans->layer_stride = ptrans->stride;
|
||||
|
||||
/* Note that the current kernel implementation is synchronous, so no
|
||||
* need to do syncing stuff here yet.
|
||||
*/
|
||||
|
||||
buf = vc4_bo_map(rsc->bo);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Failed to map bo\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*pptrans = ptrans;
|
||||
|
||||
return buf + rsc->slices[level].offset +
|
||||
box->y / util_format_get_blockheight(format) * ptrans->stride +
|
||||
box->x / util_format_get_blockwidth(format) * rsc->cpp +
|
||||
box->z * rsc->slices[level].size0;
|
||||
|
||||
fail:
|
||||
vc4_resource_transfer_unmap(pctx, ptrans);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_resource_destroy(struct pipe_screen *pscreen,
|
||||
struct pipe_resource *prsc)
|
||||
{
|
||||
struct vc4_resource *rsc = vc4_resource(prsc);
|
||||
vc4_bo_unreference(&rsc->bo);
|
||||
free(rsc);
|
||||
}
|
||||
|
||||
static boolean
|
||||
vc4_resource_get_handle(struct pipe_screen *pscreen,
|
||||
struct pipe_resource *prsc,
|
||||
struct winsys_handle *handle)
|
||||
{
|
||||
struct vc4_resource *rsc = vc4_resource(prsc);
|
||||
|
||||
return vc4_screen_bo_get_handle(pscreen, rsc->bo, rsc->slices[0].stride,
|
||||
handle);
|
||||
}
|
||||
|
||||
static const struct u_resource_vtbl vc4_resource_vtbl = {
|
||||
.resource_get_handle = vc4_resource_get_handle,
|
||||
.resource_destroy = vc4_resource_destroy,
|
||||
.transfer_map = vc4_resource_transfer_map,
|
||||
.transfer_flush_region = u_default_transfer_flush_region,
|
||||
.transfer_unmap = vc4_resource_transfer_unmap,
|
||||
.transfer_inline_write = u_default_transfer_inline_write,
|
||||
};
|
||||
|
||||
static void
|
||||
vc4_setup_slices(struct vc4_resource *rsc)
|
||||
{
|
||||
struct pipe_resource *prsc = &rsc->base.b;
|
||||
uint32_t width = prsc->width0;
|
||||
uint32_t height = prsc->height0;
|
||||
uint32_t depth = prsc->depth0;
|
||||
uint32_t offset = 0;
|
||||
|
||||
for (int i = prsc->last_level; i >= 0; i--) {
|
||||
struct vc4_resource_slice *slice = &rsc->slices[i];
|
||||
uint32_t level_width = u_minify(width, i);
|
||||
uint32_t level_height = u_minify(height, i);
|
||||
|
||||
slice->offset = offset;
|
||||
slice->stride = align(level_width * rsc->cpp, 16);
|
||||
slice->size0 = level_height * slice->stride;
|
||||
|
||||
/* Note, since we have cubes but no 3D, depth is invariant
|
||||
* with miplevel.
|
||||
*/
|
||||
offset += slice->size0 * depth;
|
||||
}
|
||||
/* XXX: align level 0 offset? */
|
||||
}
|
||||
|
||||
static struct vc4_resource *
|
||||
vc4_resource_setup(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *tmpl)
|
||||
{
|
||||
struct vc4_resource *rsc = CALLOC_STRUCT(vc4_resource);
|
||||
if (!rsc)
|
||||
return NULL;
|
||||
struct pipe_resource *prsc = &rsc->base.b;
|
||||
|
||||
*prsc = *tmpl;
|
||||
|
||||
pipe_reference_init(&prsc->reference, 1);
|
||||
prsc->screen = pscreen;
|
||||
|
||||
rsc->base.vtbl = &vc4_resource_vtbl;
|
||||
rsc->cpp = util_format_get_blocksize(tmpl->format);
|
||||
|
||||
assert(rsc->cpp);
|
||||
|
||||
return rsc;
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
vc4_resource_create(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *tmpl)
|
||||
{
|
||||
struct vc4_resource *rsc = vc4_resource_setup(pscreen, tmpl);
|
||||
struct pipe_resource *prsc = &rsc->base.b;
|
||||
|
||||
vc4_setup_slices(rsc);
|
||||
|
||||
rsc->bo = vc4_bo_alloc(vc4_screen(pscreen),
|
||||
rsc->slices[0].offset +
|
||||
rsc->slices[0].size0 * prsc->depth0,
|
||||
"resource");
|
||||
if (!rsc->bo)
|
||||
goto fail;
|
||||
|
||||
return prsc;
|
||||
fail:
|
||||
vc4_resource_destroy(pscreen, prsc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
vc4_resource_from_handle(struct pipe_screen *pscreen,
|
||||
const struct pipe_resource *tmpl,
|
||||
struct winsys_handle *handle)
|
||||
{
|
||||
struct vc4_resource *rsc = vc4_resource_setup(pscreen, tmpl);
|
||||
struct pipe_resource *prsc = &rsc->base.b;
|
||||
struct vc4_resource_slice *slice = &rsc->slices[0];
|
||||
|
||||
if (!rsc)
|
||||
return NULL;
|
||||
|
||||
rsc->bo = vc4_screen_bo_from_handle(pscreen, handle, &slice->stride);
|
||||
if (!rsc->bo)
|
||||
goto fail;
|
||||
|
||||
#ifdef USE_VC4_SIMULATOR
|
||||
slice->stride = align(prsc->width0 * rsc->cpp, 16);
|
||||
#endif
|
||||
|
||||
return prsc;
|
||||
|
||||
fail:
|
||||
vc4_resource_destroy(pscreen, prsc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct pipe_surface *
|
||||
vc4_create_surface(struct pipe_context *pctx,
|
||||
struct pipe_resource *ptex,
|
||||
const struct pipe_surface *surf_tmpl)
|
||||
{
|
||||
struct vc4_surface *surface = CALLOC_STRUCT(vc4_surface);
|
||||
|
||||
if (!surface)
|
||||
return NULL;
|
||||
|
||||
assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
|
||||
|
||||
struct pipe_surface *psurf = &surface->base;
|
||||
unsigned level = surf_tmpl->u.tex.level;
|
||||
|
||||
pipe_reference_init(&psurf->reference, 1);
|
||||
pipe_resource_reference(&psurf->texture, ptex);
|
||||
|
||||
psurf->context = pctx;
|
||||
psurf->format = surf_tmpl->format;
|
||||
psurf->width = u_minify(ptex->width0, level);
|
||||
psurf->height = u_minify(ptex->height0, level);
|
||||
psurf->u.tex.level = level;
|
||||
psurf->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
|
||||
psurf->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf)
|
||||
{
|
||||
pipe_resource_reference(&psurf->texture, NULL);
|
||||
FREE(psurf);
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
|
||||
/* XXX: Skip this if we don't have any queued drawing to it. */
|
||||
vc4->base.flush(pctx, NULL, 0);
|
||||
}
|
||||
static bool
|
||||
render_blit(struct pipe_context *ctx, struct pipe_blit_info *info)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(ctx);
|
||||
|
||||
if (!util_blitter_is_blit_supported(vc4->blitter, info)) {
|
||||
fprintf(stderr, "blit unsupported %s -> %s",
|
||||
util_format_short_name(info->src.resource->format),
|
||||
util_format_short_name(info->dst.resource->format));
|
||||
return false;
|
||||
}
|
||||
|
||||
util_blitter_save_vertex_buffer_slot(vc4->blitter, vc4->vertexbuf.vb);
|
||||
util_blitter_save_vertex_elements(vc4->blitter, vc4->vtx);
|
||||
util_blitter_save_vertex_shader(vc4->blitter, vc4->prog.vs);
|
||||
util_blitter_save_rasterizer(vc4->blitter, vc4->rasterizer);
|
||||
util_blitter_save_viewport(vc4->blitter, &vc4->viewport);
|
||||
util_blitter_save_scissor(vc4->blitter, &vc4->scissor);
|
||||
util_blitter_save_fragment_shader(vc4->blitter, vc4->prog.fs);
|
||||
util_blitter_save_blend(vc4->blitter, vc4->blend);
|
||||
util_blitter_save_depth_stencil_alpha(vc4->blitter, vc4->zsa);
|
||||
util_blitter_save_stencil_ref(vc4->blitter, &vc4->stencil_ref);
|
||||
util_blitter_save_sample_mask(vc4->blitter, vc4->sample_mask);
|
||||
util_blitter_save_framebuffer(vc4->blitter, &vc4->framebuffer);
|
||||
util_blitter_save_fragment_sampler_states(vc4->blitter,
|
||||
vc4->fragtex.num_samplers,
|
||||
(void **)vc4->fragtex.samplers);
|
||||
util_blitter_save_fragment_sampler_views(vc4->blitter,
|
||||
vc4->fragtex.num_textures, vc4->fragtex.textures);
|
||||
|
||||
util_blitter_blit(vc4->blitter, info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Optimal hardware path for blitting pixels.
|
||||
* Scaling, format conversion, up- and downsampling (resolve) are allowed.
|
||||
*/
|
||||
static void
|
||||
vc4_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
|
||||
{
|
||||
struct pipe_blit_info info = *blit_info;
|
||||
|
||||
if (info.src.resource->nr_samples > 1 &&
|
||||
info.dst.resource->nr_samples <= 1 &&
|
||||
!util_format_is_depth_or_stencil(info.src.resource->format) &&
|
||||
!util_format_is_pure_integer(info.src.resource->format)) {
|
||||
fprintf(stderr, "color resolve unimplemented");
|
||||
return;
|
||||
}
|
||||
|
||||
if (util_try_blit_via_copy_region(pctx, &info)) {
|
||||
return; /* done */
|
||||
}
|
||||
|
||||
if (info.mask & PIPE_MASK_S) {
|
||||
fprintf(stderr, "cannot blit stencil, skipping");
|
||||
info.mask &= ~PIPE_MASK_S;
|
||||
}
|
||||
|
||||
render_blit(pctx, &info);
|
||||
}
|
||||
|
||||
void
|
||||
vc4_resource_screen_init(struct pipe_screen *pscreen)
|
||||
{
|
||||
pscreen->resource_create = vc4_resource_create;
|
||||
pscreen->resource_from_handle = vc4_resource_from_handle;
|
||||
pscreen->resource_get_handle = u_resource_get_handle_vtbl;
|
||||
pscreen->resource_destroy = u_resource_destroy_vtbl;
|
||||
}
|
||||
|
||||
void
|
||||
vc4_resource_context_init(struct pipe_context *pctx)
|
||||
{
|
||||
pctx->transfer_map = u_transfer_map_vtbl;
|
||||
pctx->transfer_flush_region = u_transfer_flush_region_vtbl;
|
||||
pctx->transfer_unmap = u_transfer_unmap_vtbl;
|
||||
pctx->transfer_inline_write = u_transfer_inline_write_vtbl;
|
||||
pctx->create_surface = vc4_create_surface;
|
||||
pctx->surface_destroy = vc4_surface_destroy;
|
||||
pctx->resource_copy_region = util_resource_copy_region;
|
||||
pctx->blit = vc4_blit;
|
||||
pctx->flush_resource = vc4_flush_resource;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef VC4_RESOURCE_H
|
||||
#define VC4_RESOURCE_H
|
||||
|
||||
#include "vc4_screen.h"
|
||||
#include "util/u_transfer.h"
|
||||
|
||||
struct vc4_resource_slice {
|
||||
uint32_t offset;
|
||||
uint32_t stride;
|
||||
uint32_t size0;
|
||||
};
|
||||
|
||||
struct vc4_surface {
|
||||
struct pipe_surface base;
|
||||
uint32_t offset;
|
||||
uint32_t stride;
|
||||
uint32_t width;
|
||||
uint16_t height;
|
||||
uint16_t depth;
|
||||
};
|
||||
|
||||
struct vc4_resource {
|
||||
struct u_resource base;
|
||||
struct vc4_bo *bo;
|
||||
struct vc4_resource_slice slices[VC4_MAX_MIP_LEVELS];
|
||||
int cpp;
|
||||
};
|
||||
|
||||
static INLINE struct vc4_resource *
|
||||
vc4_resource(struct pipe_resource *prsc)
|
||||
{
|
||||
return (struct vc4_resource *)prsc;
|
||||
}
|
||||
|
||||
static INLINE struct vc4_surface *
|
||||
vc4_surface(struct pipe_surface *psurf)
|
||||
{
|
||||
return (struct vc4_surface *)psurf;
|
||||
}
|
||||
|
||||
void vc4_resource_screen_init(struct pipe_screen *pscreen);
|
||||
void vc4_resource_context_init(struct pipe_context *pctx);
|
||||
|
||||
#endif /* VC4_RESOURCE_H */
|
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
|
||||
*
|
||||
* 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 "pipe/p_defines.h"
|
||||
#include "pipe/p_screen.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include "util/u_debug.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_format.h"
|
||||
|
||||
#include "vc4_screen.h"
|
||||
#include "vc4_context.h"
|
||||
#include "vc4_resource.h"
|
||||
|
||||
static const struct debug_named_value debug_options[] = {
|
||||
{"cl", VC4_DBG_CL, "Dump command list during creation"},
|
||||
};
|
||||
|
||||
static const char *
|
||||
vc4_screen_get_name(struct pipe_screen *pscreen)
|
||||
{
|
||||
return "VC4";
|
||||
}
|
||||
|
||||
static const char *
|
||||
vc4_screen_get_vendor(struct pipe_screen *pscreen)
|
||||
{
|
||||
return "Broadcom";
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_screen_destroy(struct pipe_screen *pscreen)
|
||||
{
|
||||
free(pscreen);
|
||||
}
|
||||
|
||||
static int
|
||||
vc4_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
|
||||
{
|
||||
switch (param) {
|
||||
/* Supported features (boolean caps). */
|
||||
case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
|
||||
case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:
|
||||
case PIPE_CAP_NPOT_TEXTURES:
|
||||
case PIPE_CAP_USER_CONSTANT_BUFFERS:
|
||||
case PIPE_CAP_TEXTURE_SHADOW_MAP:
|
||||
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
|
||||
case PIPE_CAP_TWO_SIDED_STENCIL:
|
||||
return 1;
|
||||
|
||||
/* lying for GL 2.0 */
|
||||
case PIPE_CAP_OCCLUSION_QUERY:
|
||||
case PIPE_CAP_POINT_SPRITE:
|
||||
return 1;
|
||||
|
||||
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
|
||||
return 256;
|
||||
|
||||
case PIPE_CAP_GLSL_FEATURE_LEVEL:
|
||||
return 120;
|
||||
|
||||
case PIPE_CAP_MAX_VIEWPORTS:
|
||||
return 1;
|
||||
|
||||
/* Unsupported features. */
|
||||
case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
|
||||
case PIPE_CAP_ANISOTROPIC_FILTER:
|
||||
case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
|
||||
case PIPE_CAP_CUBE_MAP_ARRAY:
|
||||
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
|
||||
case PIPE_CAP_TEXTURE_SWIZZLE:
|
||||
case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
|
||||
case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
|
||||
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
|
||||
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
|
||||
case PIPE_CAP_SEAMLESS_CUBE_MAP:
|
||||
case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
|
||||
case PIPE_CAP_TGSI_INSTANCEID:
|
||||
case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
|
||||
case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
|
||||
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
|
||||
case PIPE_CAP_COMPUTE:
|
||||
case PIPE_CAP_START_INSTANCE:
|
||||
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
|
||||
case PIPE_CAP_SHADER_STENCIL_EXPORT:
|
||||
case PIPE_CAP_TGSI_TEXCOORD:
|
||||
case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
|
||||
case PIPE_CAP_CONDITIONAL_RENDER:
|
||||
case PIPE_CAP_PRIMITIVE_RESTART:
|
||||
case PIPE_CAP_TEXTURE_MULTISAMPLE:
|
||||
case PIPE_CAP_TEXTURE_BARRIER:
|
||||
case PIPE_CAP_SM3:
|
||||
case PIPE_CAP_INDEP_BLEND_ENABLE:
|
||||
case PIPE_CAP_INDEP_BLEND_FUNC:
|
||||
case PIPE_CAP_DEPTH_CLIP_DISABLE:
|
||||
case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
|
||||
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
|
||||
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
|
||||
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
|
||||
case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
|
||||
case PIPE_CAP_VERTEX_COLOR_CLAMPED:
|
||||
case PIPE_CAP_USER_VERTEX_BUFFERS:
|
||||
case PIPE_CAP_USER_INDEX_BUFFERS:
|
||||
case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
|
||||
case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
|
||||
case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT:
|
||||
case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
|
||||
case PIPE_CAP_TEXTURE_GATHER_SM5:
|
||||
case PIPE_CAP_FAKE_SW_MSAA:
|
||||
case PIPE_CAP_TEXTURE_QUERY_LOD:
|
||||
case PIPE_CAP_SAMPLE_SHADING:
|
||||
case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
|
||||
case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET:
|
||||
case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION:
|
||||
case PIPE_CAP_MAX_TEXEL_OFFSET:
|
||||
case PIPE_CAP_MAX_VERTEX_STREAMS:
|
||||
case PIPE_CAP_DRAW_INDIRECT:
|
||||
return 0;
|
||||
|
||||
/* Stream output. */
|
||||
case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
|
||||
case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
|
||||
case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
|
||||
case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
|
||||
return 0;
|
||||
|
||||
/* Geometry shader output, unsupported. */
|
||||
case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
|
||||
case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
|
||||
return 0;
|
||||
|
||||
/* Texturing. */
|
||||
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
|
||||
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
|
||||
return VC4_MAX_MIP_LEVELS;
|
||||
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
|
||||
return 1;
|
||||
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
|
||||
return 0;
|
||||
|
||||
/* Render targets. */
|
||||
case PIPE_CAP_MAX_RENDER_TARGETS:
|
||||
return 1;
|
||||
|
||||
/* Queries. */
|
||||
case PIPE_CAP_QUERY_TIME_ELAPSED:
|
||||
case PIPE_CAP_QUERY_TIMESTAMP:
|
||||
return 0;
|
||||
|
||||
case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET:
|
||||
case PIPE_CAP_MIN_TEXEL_OFFSET:
|
||||
return 0;
|
||||
|
||||
case PIPE_CAP_ENDIANNESS:
|
||||
return PIPE_ENDIAN_LITTLE;
|
||||
|
||||
case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
|
||||
return 64;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "unknown param %d\n", param);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static float
|
||||
vc4_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
|
||||
{
|
||||
switch (param) {
|
||||
case PIPE_CAPF_MAX_LINE_WIDTH:
|
||||
case PIPE_CAPF_MAX_LINE_WIDTH_AA:
|
||||
case PIPE_CAPF_MAX_POINT_WIDTH:
|
||||
case PIPE_CAPF_MAX_POINT_WIDTH_AA:
|
||||
return 8192.0f;
|
||||
case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
|
||||
return 0.0f;
|
||||
case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
|
||||
return 0.0f;
|
||||
case PIPE_CAPF_GUARD_BAND_LEFT:
|
||||
case PIPE_CAPF_GUARD_BAND_TOP:
|
||||
case PIPE_CAPF_GUARD_BAND_RIGHT:
|
||||
case PIPE_CAPF_GUARD_BAND_BOTTOM:
|
||||
return 0.0f;
|
||||
default:
|
||||
fprintf(stderr, "unknown paramf %d\n", param);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
vc4_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
|
||||
enum pipe_shader_cap param)
|
||||
{
|
||||
if (shader != PIPE_SHADER_VERTEX &&
|
||||
shader != PIPE_SHADER_FRAGMENT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this is probably not totally correct.. but it's a start: */
|
||||
switch (param) {
|
||||
case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
|
||||
case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
|
||||
case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
|
||||
case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
|
||||
return 16384;
|
||||
case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
|
||||
return 0;
|
||||
case PIPE_SHADER_CAP_MAX_INPUTS:
|
||||
return 16;
|
||||
case PIPE_SHADER_CAP_MAX_TEMPS:
|
||||
return 64; /* Max native temporaries. */
|
||||
case PIPE_SHADER_CAP_MAX_ADDRS:
|
||||
return 1; /* Max native address registers */
|
||||
case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
|
||||
return 64 * sizeof(float[4]);
|
||||
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
|
||||
return 1;
|
||||
case PIPE_SHADER_CAP_MAX_PREDS:
|
||||
return 0; /* nothing uses this */
|
||||
case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
|
||||
return 0;
|
||||
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
|
||||
case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
|
||||
case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
|
||||
case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
|
||||
return 0;
|
||||
case PIPE_SHADER_CAP_SUBROUTINES:
|
||||
return 0;
|
||||
case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
|
||||
return 0;
|
||||
case PIPE_SHADER_CAP_INTEGERS:
|
||||
case PIPE_SHADER_CAP_DOUBLES:
|
||||
return 0;
|
||||
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
|
||||
case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
|
||||
return 16;
|
||||
case PIPE_SHADER_CAP_PREFERRED_IR:
|
||||
return PIPE_SHADER_IR_TGSI;
|
||||
default:
|
||||
fprintf(stderr, "unknown shader param %d\n", param);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
vc4_get_texture_format(enum pipe_format format)
|
||||
{
|
||||
switch (format) {
|
||||
case PIPE_FORMAT_B8G8R8A8_UNORM:
|
||||
return 0;
|
||||
case PIPE_FORMAT_B8G8R8X8_UNORM:
|
||||
return 1;
|
||||
case PIPE_FORMAT_R8G8B8A8_UNORM:
|
||||
return 0;
|
||||
case PIPE_FORMAT_R8G8B8X8_UNORM:
|
||||
return 1;
|
||||
case PIPE_FORMAT_A8R8G8B8_UNORM:
|
||||
return 0;
|
||||
case PIPE_FORMAT_X8R8G8B8_UNORM:
|
||||
return 1;
|
||||
case PIPE_FORMAT_A8B8G8R8_UNORM:
|
||||
return 0;
|
||||
case PIPE_FORMAT_X8B8G8R8_UNORM:
|
||||
return 1;
|
||||
/*
|
||||
case PIPE_FORMAT_R4G4B4A4_UNORM:
|
||||
return 2;
|
||||
case PIPE_FORMAT_R5G5B5A1_UNORM:
|
||||
return 3;
|
||||
case PIPE_FORMAT_R5G6B5_UNORM:
|
||||
return 4;
|
||||
*/
|
||||
case PIPE_FORMAT_L8_UNORM:
|
||||
return 5;
|
||||
case PIPE_FORMAT_A8_UNORM:
|
||||
return 6;
|
||||
case PIPE_FORMAT_L8A8_UNORM:
|
||||
return 7;
|
||||
/* XXX: ETC1 and more*/
|
||||
default:
|
||||
return ~0;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean
|
||||
vc4_screen_is_format_supported(struct pipe_screen *pscreen,
|
||||
enum pipe_format format,
|
||||
enum pipe_texture_target target,
|
||||
unsigned sample_count,
|
||||
unsigned usage)
|
||||
{
|
||||
unsigned retval = 0;
|
||||
|
||||
if ((target >= PIPE_MAX_TEXTURE_TYPES) ||
|
||||
(sample_count > 1) ||
|
||||
!util_format_is_supported(format, usage)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (usage & PIPE_BIND_VERTEX_BUFFER)
|
||||
retval |= PIPE_BIND_VERTEX_BUFFER; /* XXX */
|
||||
|
||||
if ((usage & PIPE_BIND_RENDER_TARGET) &&
|
||||
(format == PIPE_FORMAT_B8G8R8A8_UNORM ||
|
||||
format == PIPE_FORMAT_B8G8R8X8_UNORM || /* XXX: really? */
|
||||
format == PIPE_FORMAT_R8G8B8A8_UNORM ||
|
||||
format == PIPE_FORMAT_R8G8B8X8_UNORM || /* XXX: really? */
|
||||
format == PIPE_FORMAT_A8B8G8R8_UNORM ||
|
||||
format == PIPE_FORMAT_X8B8G8R8_UNORM || /* XXX: really? */
|
||||
format == PIPE_FORMAT_A8R8G8B8_UNORM ||
|
||||
format == PIPE_FORMAT_X8R8G8B8_UNORM || /* XXX: really? */
|
||||
format == PIPE_FORMAT_R16G16B16A16_FLOAT)) {
|
||||
retval |= PIPE_BIND_RENDER_TARGET;
|
||||
}
|
||||
|
||||
if ((usage & PIPE_BIND_SAMPLER_VIEW) &&
|
||||
(vc4_get_texture_format(format) != ~0)) {
|
||||
retval |= usage & (PIPE_BIND_SAMPLER_VIEW |
|
||||
PIPE_BIND_VERTEX_BUFFER);
|
||||
}
|
||||
|
||||
if ((usage & PIPE_BIND_DEPTH_STENCIL) &&
|
||||
(format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
|
||||
format == PIPE_FORMAT_Z24X8_UNORM)) {
|
||||
retval |= PIPE_BIND_DEPTH_STENCIL;
|
||||
}
|
||||
|
||||
if ((usage & PIPE_BIND_INDEX_BUFFER) &&
|
||||
(format == PIPE_FORMAT_I8_UINT ||
|
||||
format == PIPE_FORMAT_I16_UINT)) {
|
||||
retval |= PIPE_BIND_INDEX_BUFFER;
|
||||
}
|
||||
|
||||
if (usage & PIPE_BIND_TRANSFER_READ)
|
||||
retval |= PIPE_BIND_TRANSFER_READ;
|
||||
if (usage & PIPE_BIND_TRANSFER_WRITE)
|
||||
retval |= PIPE_BIND_TRANSFER_WRITE;
|
||||
|
||||
return retval == usage;
|
||||
}
|
||||
|
||||
struct pipe_screen *
|
||||
vc4_screen_create(int fd)
|
||||
{
|
||||
struct vc4_screen *screen = CALLOC_STRUCT(vc4_screen);
|
||||
struct pipe_screen *pscreen;
|
||||
|
||||
pscreen = &screen->base;
|
||||
|
||||
pscreen->destroy = vc4_screen_destroy;
|
||||
pscreen->get_param = vc4_screen_get_param;
|
||||
pscreen->get_paramf = vc4_screen_get_paramf;
|
||||
pscreen->get_shader_param = vc4_screen_get_shader_param;
|
||||
pscreen->context_create = vc4_context_create;
|
||||
pscreen->is_format_supported = vc4_screen_is_format_supported;
|
||||
|
||||
screen->fd = fd;
|
||||
|
||||
#if USE_VC4_SIMULATOR
|
||||
vc4_simulator_init(screen);
|
||||
#endif
|
||||
|
||||
vc4_resource_screen_init(pscreen);
|
||||
|
||||
pscreen->get_name = vc4_screen_get_name;
|
||||
pscreen->get_vendor = vc4_screen_get_vendor;
|
||||
|
||||
return pscreen;
|
||||
}
|
||||
|
||||
boolean
|
||||
vc4_screen_bo_get_handle(struct pipe_screen *pscreen,
|
||||
struct vc4_bo *bo,
|
||||
unsigned stride,
|
||||
struct winsys_handle *whandle)
|
||||
{
|
||||
whandle->stride = stride;
|
||||
|
||||
switch (whandle->type) {
|
||||
case DRM_API_HANDLE_TYPE_SHARED:
|
||||
return vc4_bo_flink(bo, &whandle->handle);
|
||||
case DRM_API_HANDLE_TYPE_KMS:
|
||||
whandle->handle = bo->handle;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
struct vc4_bo *
|
||||
vc4_screen_bo_from_handle(struct pipe_screen *pscreen,
|
||||
struct winsys_handle *whandle,
|
||||
unsigned *out_stride)
|
||||
{
|
||||
struct vc4_screen *screen = vc4_screen(pscreen);
|
||||
struct vc4_bo *bo;
|
||||
|
||||
if (whandle->type != DRM_API_HANDLE_TYPE_SHARED) {
|
||||
fprintf(stderr,
|
||||
"Attempt to import unsupported handle type %d\n",
|
||||
whandle->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bo = vc4_bo_open_name(screen, whandle->handle, whandle->stride);
|
||||
if (!bo) {
|
||||
fprintf(stderr, "Open name %d failed\n", whandle->handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*out_stride = whandle->stride;
|
||||
|
||||
return bo;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef VC4_SCREEN_H
|
||||
#define VC4_SCREEN_H
|
||||
|
||||
#include "pipe/p_screen.h"
|
||||
#include "state_tracker/drm_driver.h"
|
||||
|
||||
struct vc4_bo;
|
||||
|
||||
#define VC4_DBG_CL 0x0001
|
||||
|
||||
#define VC4_MAX_MIP_LEVELS 11
|
||||
|
||||
struct vc4_screen {
|
||||
struct pipe_screen base;
|
||||
int fd;
|
||||
|
||||
void *simulator_mem_base;
|
||||
uint32_t simulator_mem_next;
|
||||
uint32_t simulator_mem_size;
|
||||
};
|
||||
|
||||
static inline struct vc4_screen *
|
||||
vc4_screen(struct pipe_screen *screen)
|
||||
{
|
||||
return (struct vc4_screen *)screen;
|
||||
}
|
||||
|
||||
struct pipe_screen *vc4_screen_create(int fd);
|
||||
boolean vc4_screen_bo_get_handle(struct pipe_screen *pscreen,
|
||||
struct vc4_bo *bo,
|
||||
unsigned stride,
|
||||
struct winsys_handle *whandle);
|
||||
struct vc4_bo *
|
||||
vc4_screen_bo_from_handle(struct pipe_screen *pscreen,
|
||||
struct winsys_handle *whandle,
|
||||
unsigned *out_stride);
|
||||
|
||||
uint8_t vc4_get_texture_format(enum pipe_format format);
|
||||
|
||||
#endif /* VC4_SCREEN_H */
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef USE_VC4_SIMULATOR
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vc4_screen.h"
|
||||
#include "vc4_context.h"
|
||||
#include "simpenrose/simpenrose.h"
|
||||
|
||||
void
|
||||
vc4_simulator_flush(struct vc4_context *vc4, struct vc4_surface *csurf)
|
||||
{
|
||||
struct vc4_resource *ctex = vc4_resource(csurf->base.texture);
|
||||
uint32_t winsys_stride = ctex->bo->simulator_winsys_stride;
|
||||
uint32_t sim_stride = ctex->slices[0].stride;
|
||||
uint32_t row_len = MIN2(sim_stride, winsys_stride);
|
||||
|
||||
if (ctex->bo->simulator_winsys_map) {
|
||||
#if 0
|
||||
fprintf(stderr, "%dx%d %d %d %d\n",
|
||||
ctex->base.b.width0, ctex->base.b.height0,
|
||||
winsys_stride,
|
||||
sim_stride,
|
||||
ctex->bo->size);
|
||||
#endif
|
||||
|
||||
for (int y = 0; y < ctex->base.b.height0; y++) {
|
||||
memcpy(ctex->bo->map + y * sim_stride,
|
||||
ctex->bo->simulator_winsys_map + y * winsys_stride,
|
||||
row_len);
|
||||
}
|
||||
}
|
||||
|
||||
simpenrose_do_binning(simpenrose_hw_addr(vc4->bcl.base),
|
||||
simpenrose_hw_addr(vc4->bcl.next));
|
||||
simpenrose_do_rendering(simpenrose_hw_addr(vc4->rcl.base),
|
||||
simpenrose_hw_addr(vc4->rcl.next));
|
||||
|
||||
if (ctex->bo->simulator_winsys_map) {
|
||||
for (int y = 0; y < ctex->base.b.height0; y++) {
|
||||
memcpy(ctex->bo->simulator_winsys_map + y * winsys_stride,
|
||||
ctex->bo->map + y * sim_stride,
|
||||
row_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vc4_simulator_init(struct vc4_screen *screen)
|
||||
{
|
||||
simpenrose_init_hardware();
|
||||
screen->simulator_mem_base = simpenrose_get_mem_start();
|
||||
screen->simulator_mem_size = simpenrose_get_mem_size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates GPU memory in the simulator's address space.
|
||||
*
|
||||
* We just allocate for the lifetime of the context now, but some day we'll
|
||||
* want an actual memory allocator at runtime.
|
||||
*/
|
||||
void *
|
||||
vc4_simulator_alloc(struct vc4_screen *screen, uint32_t size)
|
||||
{
|
||||
void *alloc = screen->simulator_mem_base + screen->simulator_mem_next;
|
||||
|
||||
screen->simulator_mem_next += size;
|
||||
assert(screen->simulator_mem_next < screen->simulator_mem_size);
|
||||
screen->simulator_mem_next = align(screen->simulator_mem_next, 4096);
|
||||
|
||||
return alloc;
|
||||
}
|
||||
|
||||
#endif /* USE_VC4_SIMULATOR */
|
|
@ -0,0 +1,444 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
|
||||
*
|
||||
* 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 "pipe/p_state.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_helpers.h"
|
||||
|
||||
#include "vc4_context.h"
|
||||
|
||||
static void *
|
||||
vc4_generic_cso_state_create(const void *src, uint32_t size)
|
||||
{
|
||||
void *dst = calloc(1, size);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
memcpy(dst, src, size);
|
||||
return dst;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso)
|
||||
{
|
||||
free(hwcso);
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_blend_color(struct pipe_context *pctx,
|
||||
const struct pipe_blend_color *blend_color)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
vc4->blend_color = *blend_color;
|
||||
vc4->dirty |= VC4_DIRTY_BLEND_COLOR;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_stencil_ref(struct pipe_context *pctx,
|
||||
const struct pipe_stencil_ref *stencil_ref)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
vc4->stencil_ref =* stencil_ref;
|
||||
vc4->dirty |= VC4_DIRTY_STENCIL_REF;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_clip_state(struct pipe_context *pctx,
|
||||
const struct pipe_clip_state *clip)
|
||||
{
|
||||
fprintf(stderr, "clip todo\n");
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
vc4->sample_mask = (uint16_t)sample_mask;
|
||||
vc4->dirty |= VC4_DIRTY_SAMPLE_MASK;
|
||||
}
|
||||
|
||||
static void *
|
||||
vc4_create_rasterizer_state(struct pipe_context *pctx,
|
||||
const struct pipe_rasterizer_state *cso)
|
||||
{
|
||||
struct vc4_rasterizer_state *so;
|
||||
|
||||
so = CALLOC_STRUCT(vc4_rasterizer_state);
|
||||
if (!so)
|
||||
return NULL;
|
||||
|
||||
so->base = *cso;
|
||||
|
||||
if (!(cso->cull_face & PIPE_FACE_FRONT))
|
||||
so->config_bits[0] |= VC4_CONFIG_BITS_ENABLE_PRIM_FRONT;
|
||||
if (!(cso->cull_face & PIPE_FACE_BACK))
|
||||
so->config_bits[0] |= VC4_CONFIG_BITS_ENABLE_PRIM_BACK;
|
||||
|
||||
/* XXX: per_vertex */
|
||||
so->point_size = cso->point_size;
|
||||
|
||||
if (!cso->front_ccw)
|
||||
so->config_bits[0] |= VC4_CONFIG_BITS_CW_PRIMITIVES;
|
||||
|
||||
if (cso->offset_tri)
|
||||
so->config_bits[0] |= VC4_CONFIG_BITS_ENABLE_DEPTH_OFFSET;
|
||||
|
||||
so->config_bits[2] |= VC4_CONFIG_BITS_EARLY_Z_UPDATE;
|
||||
|
||||
return so;
|
||||
}
|
||||
|
||||
/* Blend state is baked into shaders. */
|
||||
static void *
|
||||
vc4_create_blend_state(struct pipe_context *pctx,
|
||||
const struct pipe_blend_state *cso)
|
||||
{
|
||||
return vc4_generic_cso_state_create(cso, sizeof(*cso));
|
||||
}
|
||||
|
||||
static void *
|
||||
vc4_create_depth_stencil_alpha_state(struct pipe_context *pctx,
|
||||
const struct pipe_depth_stencil_alpha_state *cso)
|
||||
{
|
||||
return vc4_generic_cso_state_create(cso, sizeof(*cso));
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_polygon_stipple(struct pipe_context *pctx,
|
||||
const struct pipe_poly_stipple *stipple)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
vc4->stipple = *stipple;
|
||||
vc4->dirty |= VC4_DIRTY_STIPPLE;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_scissor_states(struct pipe_context *pctx,
|
||||
unsigned start_slot,
|
||||
unsigned num_scissors,
|
||||
const struct pipe_scissor_state *scissor)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
|
||||
vc4->scissor = *scissor;
|
||||
vc4->dirty |= VC4_DIRTY_SCISSOR;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_viewport_states(struct pipe_context *pctx,
|
||||
unsigned start_slot,
|
||||
unsigned num_viewports,
|
||||
const struct pipe_viewport_state *viewport)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
vc4->viewport = *viewport;
|
||||
vc4->dirty |= VC4_DIRTY_VIEWPORT;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_vertex_buffers(struct pipe_context *pctx,
|
||||
unsigned start_slot, unsigned count,
|
||||
const struct pipe_vertex_buffer *vb)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
struct vc4_vertexbuf_stateobj *so = &vc4->vertexbuf;
|
||||
|
||||
util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb,
|
||||
start_slot, count);
|
||||
so->count = util_last_bit(so->enabled_mask);
|
||||
|
||||
vc4->dirty |= VC4_DIRTY_VTXBUF;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_index_buffer(struct pipe_context *pctx,
|
||||
const struct pipe_index_buffer *ib)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
|
||||
if (ib) {
|
||||
pipe_resource_reference(&vc4->indexbuf.buffer, ib->buffer);
|
||||
vc4->indexbuf.index_size = ib->index_size;
|
||||
vc4->indexbuf.offset = ib->offset;
|
||||
vc4->indexbuf.user_buffer = ib->user_buffer;
|
||||
} else {
|
||||
pipe_resource_reference(&vc4->indexbuf.buffer, NULL);
|
||||
}
|
||||
|
||||
vc4->dirty |= VC4_DIRTY_INDEXBUF;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_blend_state_bind(struct pipe_context *pctx, void *hwcso)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
vc4->blend = hwcso;
|
||||
vc4->dirty |= VC4_DIRTY_BLEND;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
vc4->rasterizer = hwcso;
|
||||
vc4->dirty |= VC4_DIRTY_RASTERIZER;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_zsa_state_bind(struct pipe_context *pctx, void *hwcso)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
vc4->zsa = hwcso;
|
||||
vc4->dirty |= VC4_DIRTY_ZSA;
|
||||
}
|
||||
|
||||
static void *
|
||||
vc4_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
|
||||
const struct pipe_vertex_element *elements)
|
||||
{
|
||||
struct vc4_vertex_stateobj *so = CALLOC_STRUCT(vc4_vertex_stateobj);
|
||||
|
||||
if (!so)
|
||||
return NULL;
|
||||
|
||||
memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
|
||||
so->num_elements = num_elements;
|
||||
|
||||
return so;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_vertex_state_bind(struct pipe_context *pctx, void *hwcso)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
vc4->vtx = hwcso;
|
||||
vc4->dirty |= VC4_DIRTY_VTXSTATE;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index,
|
||||
struct pipe_constant_buffer *cb)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
struct vc4_constbuf_stateobj *so = &vc4->constbuf[shader];
|
||||
|
||||
assert(index == 0);
|
||||
|
||||
/* Note that the state tracker can unbind constant buffers by
|
||||
* passing NULL here.
|
||||
*/
|
||||
if (unlikely(!cb)) {
|
||||
so->enabled_mask &= ~(1 << index);
|
||||
so->dirty_mask &= ~(1 << index);
|
||||
pipe_resource_reference(&so->cb[index].buffer, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
pipe_resource_reference(&so->cb[index].buffer, cb->buffer);
|
||||
so->cb[index].buffer_offset = cb->buffer_offset;
|
||||
so->cb[index].buffer_size = cb->buffer_size;
|
||||
so->cb[index].user_buffer = cb->user_buffer;
|
||||
|
||||
so->enabled_mask |= 1 << index;
|
||||
so->dirty_mask |= 1 << index;
|
||||
vc4->dirty |= VC4_DIRTY_CONSTBUF;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_framebuffer_state(struct pipe_context *pctx,
|
||||
const struct pipe_framebuffer_state *framebuffer)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
struct pipe_framebuffer_state *cso = &vc4->framebuffer;
|
||||
unsigned i;
|
||||
|
||||
vc4_flush(pctx);
|
||||
|
||||
for (i = 0; i < framebuffer->nr_cbufs; i++)
|
||||
pipe_surface_reference(&cso->cbufs[i], framebuffer->cbufs[i]);
|
||||
for (; i < vc4->framebuffer.nr_cbufs; i++)
|
||||
pipe_surface_reference(&cso->cbufs[i], NULL);
|
||||
|
||||
cso->nr_cbufs = framebuffer->nr_cbufs;
|
||||
|
||||
cso->width = framebuffer->width;
|
||||
cso->height = framebuffer->height;
|
||||
|
||||
pipe_surface_reference(&cso->zsbuf, framebuffer->zsbuf);
|
||||
|
||||
vc4->dirty |= VC4_DIRTY_FRAMEBUFFER;
|
||||
}
|
||||
|
||||
static struct vc4_texture_stateobj *
|
||||
vc4_get_stage_tex(struct vc4_context *vc4, unsigned shader)
|
||||
{
|
||||
vc4->dirty |= VC4_DIRTY_TEXSTATE;
|
||||
|
||||
switch (shader) {
|
||||
case PIPE_SHADER_FRAGMENT:
|
||||
vc4->dirty |= VC4_DIRTY_FRAGTEX;
|
||||
return &vc4->fragtex;
|
||||
break;
|
||||
case PIPE_SHADER_VERTEX:
|
||||
vc4->dirty |= VC4_DIRTY_VERTTEX;
|
||||
return &vc4->verttex;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown shader target %d\n", shader);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
vc4_create_sampler_state(struct pipe_context *pctx,
|
||||
const struct pipe_sampler_state *cso)
|
||||
{
|
||||
return vc4_generic_cso_state_create(cso, sizeof(*cso));
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_sampler_states_bind(struct pipe_context *pctx,
|
||||
unsigned shader, unsigned start,
|
||||
unsigned nr, void **hwcso)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
struct vc4_texture_stateobj *stage_tex = vc4_get_stage_tex(vc4, shader);
|
||||
|
||||
assert(start == 0);
|
||||
unsigned i;
|
||||
unsigned new_nr = 0;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
if (hwcso[i])
|
||||
new_nr = i + 1;
|
||||
stage_tex->samplers[i] = hwcso[i];
|
||||
stage_tex->dirty_samplers |= (1 << i);
|
||||
}
|
||||
|
||||
for (; i < stage_tex->num_samplers; i++) {
|
||||
stage_tex->samplers[i] = NULL;
|
||||
stage_tex->dirty_samplers |= (1 << i);
|
||||
}
|
||||
|
||||
stage_tex->num_samplers = new_nr;
|
||||
}
|
||||
|
||||
static struct pipe_sampler_view *
|
||||
vc4_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
|
||||
const struct pipe_sampler_view *cso)
|
||||
{
|
||||
struct pipe_sampler_view *so = malloc(sizeof(*so));
|
||||
|
||||
if (!so)
|
||||
return NULL;
|
||||
|
||||
*so = *cso;
|
||||
pipe_reference(NULL, &prsc->reference);
|
||||
so->texture = prsc;
|
||||
so->reference.count = 1;
|
||||
so->context = pctx;
|
||||
|
||||
return so;
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_sampler_view_destroy(struct pipe_context *pctx,
|
||||
struct pipe_sampler_view *view)
|
||||
{
|
||||
pipe_resource_reference(&view->texture, NULL);
|
||||
free(view);
|
||||
}
|
||||
|
||||
static void
|
||||
vc4_set_sampler_views(struct pipe_context *pctx, unsigned shader,
|
||||
unsigned start, unsigned nr,
|
||||
struct pipe_sampler_view **views)
|
||||
{
|
||||
struct vc4_context *vc4 = vc4_context(pctx);
|
||||
struct vc4_texture_stateobj *stage_tex = vc4_get_stage_tex(vc4, shader);
|
||||
unsigned i;
|
||||
unsigned new_nr = 0;
|
||||
|
||||
assert(start == 0);
|
||||
|
||||
vc4->dirty |= VC4_DIRTY_TEXSTATE;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
if (views[i])
|
||||
new_nr = i + 1;
|
||||
pipe_sampler_view_reference(&stage_tex->textures[i], views[i]);
|
||||
stage_tex->dirty_samplers |= (1 << i);
|
||||
}
|
||||
|
||||
for (; i < stage_tex->num_textures; i++) {
|
||||
pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
|
||||
stage_tex->dirty_samplers |= (1 << i);
|
||||
}
|
||||
|
||||
stage_tex->num_textures = new_nr;
|
||||
}
|
||||
|
||||
void
|
||||
vc4_state_init(struct pipe_context *pctx)
|
||||
{
|
||||
pctx->set_blend_color = vc4_set_blend_color;
|
||||
pctx->set_stencil_ref = vc4_set_stencil_ref;
|
||||
pctx->set_clip_state = vc4_set_clip_state;
|
||||
pctx->set_sample_mask = vc4_set_sample_mask;
|
||||
pctx->set_constant_buffer = vc4_set_constant_buffer;
|
||||
pctx->set_framebuffer_state = vc4_set_framebuffer_state;
|
||||
pctx->set_polygon_stipple = vc4_set_polygon_stipple;
|
||||
pctx->set_scissor_states = vc4_set_scissor_states;
|
||||
pctx->set_viewport_states = vc4_set_viewport_states;
|
||||
|
||||
pctx->set_vertex_buffers = vc4_set_vertex_buffers;
|
||||
pctx->set_index_buffer = vc4_set_index_buffer;
|
||||
|
||||
pctx->create_blend_state = vc4_create_blend_state;
|
||||
pctx->bind_blend_state = vc4_blend_state_bind;
|
||||
pctx->delete_blend_state = vc4_generic_cso_state_delete;
|
||||
|
||||
pctx->create_rasterizer_state = vc4_create_rasterizer_state;
|
||||
pctx->bind_rasterizer_state = vc4_rasterizer_state_bind;
|
||||
pctx->delete_rasterizer_state = vc4_generic_cso_state_delete;
|
||||
|
||||
pctx->create_depth_stencil_alpha_state = vc4_create_depth_stencil_alpha_state;
|
||||
pctx->bind_depth_stencil_alpha_state = vc4_zsa_state_bind;
|
||||
pctx->delete_depth_stencil_alpha_state = vc4_generic_cso_state_delete;
|
||||
|
||||
pctx->create_vertex_elements_state = vc4_vertex_state_create;
|
||||
pctx->delete_vertex_elements_state = vc4_generic_cso_state_delete;
|
||||
pctx->bind_vertex_elements_state = vc4_vertex_state_bind;
|
||||
|
||||
pctx->create_sampler_state = vc4_create_sampler_state;
|
||||
pctx->delete_sampler_state = vc4_generic_cso_state_delete;
|
||||
pctx->bind_sampler_states = vc4_sampler_states_bind;
|
||||
|
||||
pctx->create_sampler_view = vc4_create_sampler_view;
|
||||
pctx->sampler_view_destroy = vc4_sampler_view_destroy;
|
||||
pctx->set_sampler_views = vc4_set_sampler_views;
|
||||
}
|
|
@ -141,6 +141,18 @@ STATIC_TARGET_LIB_DEPS += \
|
|||
|
||||
endif
|
||||
|
||||
if HAVE_GALLIUM_VC4
|
||||
MEGADRIVERS += vc4
|
||||
STATIC_TARGET_CPPFLAGS += -DGALLIUM_VC4
|
||||
STATIC_TARGET_LIB_DEPS += \
|
||||
$(top_builddir)/src/gallium/winsys/vc4/drm/libvc4drm.la \
|
||||
$(top_builddir)/src/gallium/drivers/vc4/libvc4.la
|
||||
|
||||
if USE_VC4_SIMULATOR
|
||||
STATIC_TARGET_CPPFLAGS += -DUSE_VC4_SIMULATOR
|
||||
endif
|
||||
endif
|
||||
|
||||
if HAVE_GALLIUM_SOFTPIPE
|
||||
MEGADRIVERS += swrast
|
||||
STATIC_TARGET_CPPFLAGS += -DGALLIUM_SOFTPIPE
|
||||
|
|
|
@ -70,4 +70,8 @@ endif
|
|||
if HAVE_GALLIUM_SVGA
|
||||
SUBDIRS += svga/drm
|
||||
endif
|
||||
|
||||
if HAVE_GALLIUM_VC4
|
||||
SUBDIRS += vc4/drm
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# Copyright © 2014 Broadcom
|
||||
#
|
||||
# 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 Makefile.sources
|
||||
include $(top_srcdir)/src/gallium/Automake.inc
|
||||
|
||||
AM_CFLAGS = \
|
||||
-I$(top_srcdir)/src/gallium/drivers \
|
||||
$(GALLIUM_WINSYS_CFLAGS)
|
||||
|
||||
noinst_LTLIBRARIES = libvc4drm.la
|
||||
|
||||
libvc4drm_la_SOURCES = $(C_SOURCES)
|
|
@ -0,0 +1,2 @@
|
|||
C_SOURCES := \
|
||||
vc4_drm_winsys.c
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __VC4_DRM_PUBLIC_H__
|
||||
#define __VC4_DRM_PUBLIC_H__
|
||||
|
||||
struct pipe_screen;
|
||||
|
||||
struct pipe_screen *vc4_drm_screen_create(int drmFD);
|
||||
|
||||
#endif /* __VC4_DRM_PUBLIC_H__ */
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright © 2014 Broadcom
|
||||
*
|
||||
* 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 <unistd.h>
|
||||
|
||||
#include "vc4_drm_public.h"
|
||||
|
||||
#include "vc4/vc4_screen.h"
|
||||
|
||||
struct pipe_screen *
|
||||
vc4_drm_screen_create(int fd)
|
||||
{
|
||||
return vc4_screen_create(dup(fd));
|
||||
}
|
Loading…
Reference in New Issue