freedreno/a3xx: don't use half precision shaders for int/float32
authorIlia Mirkin <imirkin@alum.mit.edu>
Sat, 29 Nov 2014 07:13:07 +0000 (02:13 -0500)
committerIlia Mirkin <imirkin@alum.mit.edu>
Sun, 30 Nov 2014 18:04:28 +0000 (13:04 -0500)
Integer outputs end up getting mangled due to cov.f32f16, and float32
loses precision. Use full precision shaders in both of those cases.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/freedreno/a3xx/fd3_draw.c
src/gallium/drivers/freedreno/a3xx/fd3_format.h
src/gallium/drivers/freedreno/a3xx/fd3_gmem.c

index ff6db58f783e78a5d3ea11630f21d6116a554b2f..2ae4cfbcbd97eeb5a5f573fc1e0b98ffd1d9c680 100644 (file)
@@ -220,6 +220,8 @@ fd3_clear(struct fd_context *ctx, unsigned buffers,
                const union pipe_color_union *color, double depth, unsigned stencil)
 {
        struct fd3_context *fd3_ctx = fd3_context(ctx);
+       struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
+       enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);
        struct fd_ringbuffer *ring = ctx->ring;
        unsigned dirty = ctx->dirty;
        unsigned ce, i;
@@ -227,8 +229,9 @@ fd3_clear(struct fd_context *ctx, unsigned buffers,
                .vtx  = &fd3_ctx->solid_vbuf_state,
                .prog = &ctx->solid_prog,
                .key = {
-                       .half_precision = true,
+                       .half_precision = fd3_half_precision(format),
                },
+               .format = format,
        };
 
        dirty &= FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR;
index ebd67959c7b25e4c6894dc14ffe63061bc666f02..043454e2733f2abdecd647131a338a86c856c40d 100644 (file)
@@ -25,6 +25,7 @@
 #ifndef FD3_FORMAT_H_
 #define FD3_FORMAT_H_
 
+#include "util/u_format.h"
 #include "freedreno_util.h"
 
 #include "a3xx.xml.h"
@@ -39,4 +40,21 @@ enum a3xx_color_swap fd3_pipe2swap(enum pipe_format format);
 uint32_t fd3_tex_swiz(enum pipe_format format, unsigned swizzle_r,
                unsigned swizzle_g, unsigned swizzle_b, unsigned swizzle_a);
 
+static INLINE bool
+fd3_half_precision(enum pipe_format format)
+{
+       /* colors are provided in consts, which go through cov.f32f16, which will
+        * break these values
+        */
+       if (util_format_is_pure_integer(format))
+               return false;
+
+       /* avoid losing precision on 32-bit float formats */
+       if (util_format_is_float(format) &&
+               util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) == 32)
+               return false;
+
+       return true;
+}
+
 #endif /* FD3_FORMAT_H_ */
index dae0b1136354b11a187ee2a3505d6627e4dc6268..8edfb8b46d192ed1bbde1484f5ce40ed6c67132f 100644 (file)
 #include "fd3_format.h"
 #include "fd3_zsa.h"
 
-static const struct ir3_shader_key key = {
-               // XXX should set this based on render target format!  We don't
-               // want half_precision if float32 render target!!!
-               .half_precision = true,
-};
-
 static void
 emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
                struct pipe_surface **bufs, uint32_t *bases, uint32_t bin_w)
@@ -161,7 +155,9 @@ emit_binning_workaround(struct fd_context *ctx)
        struct fd3_emit emit = {
                        .vtx = &fd3_ctx->solid_vbuf_state,
                        .prog = &ctx->solid_prog,
-                       .key = key,
+                       .key = {
+                               .half_precision = true,
+                       },
        };
 
        OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 2);
@@ -336,10 +332,14 @@ fd3_emit_tile_gmem2mem(struct fd_context *ctx, struct fd_tile *tile)
        struct fd3_context *fd3_ctx = fd3_context(ctx);
        struct fd_ringbuffer *ring = ctx->ring;
        struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
+       enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);
        struct fd3_emit emit = {
                        .vtx = &fd3_ctx->solid_vbuf_state,
                        .prog = &ctx->solid_prog,
-                       .key = key,
+                       .key = {
+                               .half_precision = fd3_half_precision(format),
+                       },
+                       .format = format,
        };
 
        OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
@@ -458,10 +458,14 @@ fd3_emit_tile_mem2gmem(struct fd_context *ctx, struct fd_tile *tile)
        struct fd_gmem_stateobj *gmem = &ctx->gmem;
        struct fd_ringbuffer *ring = ctx->ring;
        struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
+       enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);
        struct fd3_emit emit = {
                        .vtx = &fd3_ctx->blit_vbuf_state,
                        .prog = &ctx->blit_prog,
-                       .key = key,
+                       .key = {
+                               .half_precision = fd3_half_precision(format),
+                       },
+                       .format = format,
        };
        float x0, y0, x1, y1;
        unsigned bin_w = tile->bin_w;