[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