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 <imir...@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

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to