summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2018-11-28 17:22:45 -0800
committerEric Anholt <[email protected]>2018-12-14 17:48:01 -0800
commit6ad9e8690d144f110150d3367254504c1b322682 (patch)
tree7e8f987b4f74e27da90c1f2c5a2df71e117d773b
parent976ea90bdca2b1fc9e7a577ddc302e810c622183 (diff)
v3d: Add support for texturing from linear.
Just like vc4, we have to support linear shared BOs for X11 on arbitrary displays. When we're faced with a request to texture from one of those, make a shadow image that we copy using the TFU at the start of the draw call.
-rw-r--r--src/gallium/drivers/v3d/v3d_context.h6
-rw-r--r--src/gallium/drivers/v3d/v3d_resource.c55
-rw-r--r--src/gallium/drivers/v3d/v3d_resource.h2
-rw-r--r--src/gallium/drivers/v3d/v3d_uniforms.c2
-rw-r--r--src/gallium/drivers/v3d/v3dx_draw.c8
-rw-r--r--src/gallium/drivers/v3d/v3dx_state.c40
6 files changed, 110 insertions, 3 deletions
diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h
index a2fcf1ae2d4..575b74f4940 100644
--- a/src/gallium/drivers/v3d/v3d_context.h
+++ b/src/gallium/drivers/v3d/v3d_context.h
@@ -95,6 +95,12 @@ struct v3d_sampler_view {
uint8_t texture_shader_state[32];
/* V3D 4.x: Texture state struct. */
struct v3d_bo *bo;
+
+ /* Actual texture to be read by this sampler view. May be different
+ * from base.texture in the case of having a shadow tiled copy of a
+ * raster texture.
+ */
+ struct pipe_resource *texture;
};
struct v3d_sampler_state {
diff --git a/src/gallium/drivers/v3d/v3d_resource.c b/src/gallium/drivers/v3d/v3d_resource.c
index 6c69cbe03f7..33b44868bbd 100644
--- a/src/gallium/drivers/v3d/v3d_resource.c
+++ b/src/gallium/drivers/v3d/v3d_resource.c
@@ -828,6 +828,61 @@ fail:
return NULL;
}
+void
+v3d_update_shadow_texture(struct pipe_context *pctx,
+ struct pipe_sampler_view *pview)
+{
+ struct v3d_sampler_view *view = v3d_sampler_view(pview);
+ struct v3d_resource *shadow = v3d_resource(view->texture);
+ struct v3d_resource *orig = v3d_resource(pview->texture);
+
+ assert(view->texture != pview->texture);
+
+ if (shadow->writes == orig->writes && orig->bo->private)
+ return;
+
+ perf_debug("Updating %dx%d@%d shadow for linear texture\n",
+ orig->base.width0, orig->base.height0,
+ pview->u.tex.first_level);
+
+ for (int i = 0; i <= shadow->base.last_level; i++) {
+ unsigned width = u_minify(shadow->base.width0, i);
+ unsigned height = u_minify(shadow->base.height0, i);
+ struct pipe_blit_info info = {
+ .dst = {
+ .resource = &shadow->base,
+ .level = i,
+ .box = {
+ .x = 0,
+ .y = 0,
+ .z = 0,
+ .width = width,
+ .height = height,
+ .depth = 1,
+ },
+ .format = shadow->base.format,
+ },
+ .src = {
+ .resource = &orig->base,
+ .level = pview->u.tex.first_level + i,
+ .box = {
+ .x = 0,
+ .y = 0,
+ .z = 0,
+ .width = width,
+ .height = height,
+ .depth = 1,
+ },
+ .format = orig->base.format,
+ },
+ .mask = util_format_get_mask(orig->base.format),
+ };
+ pctx->blit(pctx, &info);
+ }
+
+ shadow->writes = orig->writes;
+}
+
static struct pipe_surface *
v3d_create_surface(struct pipe_context *pctx,
struct pipe_resource *ptex,
diff --git a/src/gallium/drivers/v3d/v3d_resource.h b/src/gallium/drivers/v3d/v3d_resource.h
index 80b1d6eb9ad..2aa28627338 100644
--- a/src/gallium/drivers/v3d/v3d_resource.h
+++ b/src/gallium/drivers/v3d/v3d_resource.h
@@ -176,6 +176,8 @@ void v3d_resource_screen_init(struct pipe_screen *pscreen);
void v3d_resource_context_init(struct pipe_context *pctx);
struct pipe_resource *v3d_resource_create(struct pipe_screen *pscreen,
const struct pipe_resource *tmpl);
+void v3d_update_shadow_texture(struct pipe_context *pctx,
+ struct pipe_sampler_view *view);
uint32_t v3d_layer_offset(struct pipe_resource *prsc, uint32_t level,
uint32_t layer);
diff --git a/src/gallium/drivers/v3d/v3d_uniforms.c b/src/gallium/drivers/v3d/v3d_uniforms.c
index 49e83ccdb1d..c924c2f2e04 100644
--- a/src/gallium/drivers/v3d/v3d_uniforms.c
+++ b/src/gallium/drivers/v3d/v3d_uniforms.c
@@ -151,7 +151,7 @@ write_tmu_p0(struct v3d_job *job,
int unit = v3d_tmu_config_data_get_unit(data);
struct pipe_sampler_view *psview = texstate->textures[unit];
struct v3d_sampler_view *sview = v3d_sampler_view(psview);
- struct v3d_resource *rsc = v3d_resource(psview->texture);
+ struct v3d_resource *rsc = v3d_resource(sview->texture);
cl_aligned_reloc(&job->indirect, uniforms, sview->bo,
v3d_tmu_config_data_get_value(data));
diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c
index ca0a1ab39c2..d48970e1e2b 100644
--- a/src/gallium/drivers/v3d/v3dx_draw.c
+++ b/src/gallium/drivers/v3d/v3dx_draw.c
@@ -126,9 +126,13 @@ v3d_predraw_check_stage_inputs(struct pipe_context *pctx,
/* Flush writes to textures we're sampling. */
for (int i = 0; i < v3d->tex[s].num_textures; i++) {
- struct pipe_sampler_view *view = v3d->tex[s].textures[i];
- if (!view)
+ struct pipe_sampler_view *pview = v3d->tex[s].textures[i];
+ if (!pview)
continue;
+ struct v3d_sampler_view *view = v3d_sampler_view(pview);
+
+ if (view->texture != view->base.texture)
+ v3d_update_shadow_texture(pctx, &view->base);
v3d_flush_jobs_writing_resource(v3d, view->texture);
}
diff --git a/src/gallium/drivers/v3d/v3dx_state.c b/src/gallium/drivers/v3d/v3dx_state.c
index 2980547f1d6..ee1ba7b2d10 100644
--- a/src/gallium/drivers/v3d/v3dx_state.c
+++ b/src/gallium/drivers/v3d/v3dx_state.c
@@ -746,6 +746,7 @@ v3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
struct v3d_context *v3d = v3d_context(pctx);
struct v3d_screen *screen = v3d->screen;
struct v3d_sampler_view *so = CALLOC_STRUCT(v3d_sampler_view);
+ struct v3d_resource *rsc = v3d_resource(prsc);
if (!so)
return NULL;
@@ -772,6 +773,44 @@ v3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
so->base.reference.count = 1;
so->base.context = pctx;
+ /* V3D still doesn't support sampling from raster textures, so we will
+ * have to copy to a temporary tiled texture.
+ */
+ if (!rsc->tiled) {
+ struct v3d_resource *shadow_parent = rsc;
+ struct pipe_resource tmpl = {
+ .target = prsc->target,
+ .format = prsc->format,
+ .width0 = u_minify(prsc->width0,
+ cso->u.tex.first_level),
+ .height0 = u_minify(prsc->height0,
+ cso->u.tex.first_level),
+ .depth0 = 1,
+ .array_size = 1,
+ .bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
+ .last_level = cso->u.tex.last_level - cso->u.tex.first_level,
+ .nr_samples = prsc->nr_samples,
+ };
+
+ /* Create the shadow texture. The rest of the sampler view
+ * setup will use the shadow.
+ */
+ prsc = v3d_resource_create(pctx->screen, &tmpl);
+ if (!prsc) {
+ free(so);
+ return NULL;
+ }
+ rsc = v3d_resource(prsc);
+
+ /* Flag it as needing update of the contents from the parent. */
+ rsc->writes = shadow_parent->writes - 1;
+ assert(rsc->tiled);
+
+ so->texture = prsc;
+ } else {
+ pipe_resource_reference(&so->texture, prsc);
+ }
+
void *map;
#if V3D_VERSION >= 40
so->bo = v3d_bo_alloc(v3d->screen,
@@ -859,6 +898,7 @@ v3d_sampler_view_destroy(struct pipe_context *pctx,
v3d_bo_unreference(&sview->bo);
pipe_resource_reference(&psview->texture, NULL);
+ pipe_resource_reference(&sview->texture, NULL);
free(psview);
}