[Freedreno] [PATCH] freedreno/a3xx: allow texture buffer objects up to 64M texels

Ilia Mirkin imirkin at alum.mit.edu
Fri Sep 18 01:12:37 PDT 2015


This artificially converts a buffer into a 8K x N 2D texture to fetch
texels from. As a result we can access up to 8K x 8K texels.

Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
---
 src/gallium/drivers/freedreno/a3xx/fd3_texture.c     | 19 +++++++++++++------
 src/gallium/drivers/freedreno/freedreno_screen.c     |  8 ++------
 src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c |  5 ++++-
 3 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_texture.c b/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
index 6ed5e0c..c6b1e6b 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
@@ -189,10 +189,10 @@ tex_type(unsigned target)
 	switch (target) {
 	default:
 		assert(0);
-	case PIPE_BUFFER:
 	case PIPE_TEXTURE_1D:
 	case PIPE_TEXTURE_1D_ARRAY:
 		return A3XX_TEX_1D;
+	case PIPE_BUFFER:
 	case PIPE_TEXTURE_RECT:
 	case PIPE_TEXTURE_2D:
 	case PIPE_TEXTURE_2D_ARRAY:
@@ -235,12 +235,19 @@ fd3_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
 		so->texconst0 |= A3XX_TEX_CONST_0_SRGB;
 
 	if (prsc->target == PIPE_BUFFER) {
+		/* NOTE: This can end up allowing the shader to access up to 8k of
+		 * data outside of the texture. This can be avoided by clamping the
+		 * texture buffer address in the shader.
+		 */
+		unsigned elements = cso->u.buf.last_element -
+			cso->u.buf.first_element + 1;
 		lvl = 0;
 		so->texconst1 =
 			A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) |
-			A3XX_TEX_CONST_1_WIDTH(cso->u.buf.last_element -
-								   cso->u.buf.first_element + 1) |
-			A3XX_TEX_CONST_1_HEIGHT(1);
+			A3XX_TEX_CONST_1_WIDTH(MIN2(elements, 8192)) |
+			A3XX_TEX_CONST_1_HEIGHT(DIV_ROUND_UP(elements, 8192));
+		so->texconst2 =
+			A3XX_TEX_CONST_2_PITCH(MIN2(elements, 8192) * util_format_get_blocksize(cso->format));
 	} else {
 		unsigned miplevels;
 
@@ -252,10 +259,10 @@ fd3_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
 			A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) |
 			A3XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) |
 			A3XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl));
+		so->texconst2 =
+			A3XX_TEX_CONST_2_PITCH(util_format_get_nblocksx(cso->format, rsc->slices[lvl].pitch) * rsc->cpp);
 	}
 	/* when emitted, A3XX_TEX_CONST_2_INDX() must be OR'd in: */
-	so->texconst2 =
-			A3XX_TEX_CONST_2_PITCH(util_format_get_nblocksx(cso->format, rsc->slices[lvl].pitch) * rsc->cpp);
 	switch (prsc->target) {
 	case PIPE_TEXTURE_1D_ARRAY:
 	case PIPE_TEXTURE_2D_ARRAY:
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
index dabdd0a..12586dc 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.c
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c
@@ -180,12 +180,8 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
 	case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
 		return is_a3xx(screen) ? 16 : 0;
 	case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
-		/* I think 32k on a4xx.. and we could possibly emulate more
-		 * by pretending 2d/rect textures and splitting high bits
-		 * of index into 2nd dimension..
-		 */
-		if (is_a3xx(screen)) return 8192;
-		if (is_a4xx(screen)) return 16383;
+		if (is_a3xx(screen)) return 8192 * 8192;
+		if (is_a4xx(screen)) return 8192; /* TODO: Convert to 2D approach */
 		return 0;
 
 	case PIPE_CAP_DEPTH_CLIP_DISABLE:
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
index 83a1385..f3827bf 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
@@ -1657,7 +1657,10 @@ emit_tex(struct ir3_compile *ctx, nir_tex_instr *tex)
 	for (i = 0; i < coords; i++)
 		src0[nsrc0++] = coord[i];
 
-	if (coords == 1) {
+	if (tex->sampler_dim == GLSL_SAMPLER_DIM_BUF) {
+		src0[0] = ir3_AND_B(b, coord[0], 0, create_immed(b, 0x1fff), 0);
+		src0[nsrc0++] = ir3_SHR_B(b, coord[0], 0, create_immed(b, 13), 0);
+	} else if (coords == 1) {
 		/* hw doesn't do 1d, so we treat it as 2d with
 		 * height of 1, and patch up the y coord.
 		 * TODO: y coord should be (int)0 in some cases..
-- 
2.4.6



More information about the Freedreno mailing list