i965: Support GL_FIXED and packed vertex formats natively on Haswell+.
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 4 Jan 2013 15:53:12 +0000 (07:53 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Tue, 8 Jan 2013 00:48:02 +0000 (16:48 -0800)
Haswell and later support the GL_FIXED and 2_10_10_10_rev vertex formats
natively, and don't need shader workarounds.

Reviewed-by: Eric Anholt <eric@anholt.net>
src/mesa/drivers/dri/i965/brw_draw_upload.c
src/mesa/drivers/dri/i965/brw_vs.c

index 515a7a8a50ce01109161ea77cbaa6f9811ebad56..8e1b9bb28e5b84c963a037feef1e0590f2658edd 100644 (file)
@@ -65,6 +65,14 @@ static GLuint half_float_types[5] = {
    BRW_SURFACEFORMAT_R16G16B16A16_FLOAT
 };
 
+static GLuint fixed_point_types[5] = {
+   0,
+   BRW_SURFACEFORMAT_R32_SFIXED,
+   BRW_SURFACEFORMAT_R32G32_SFIXED,
+   BRW_SURFACEFORMAT_R32G32B32_SFIXED,
+   BRW_SURFACEFORMAT_R32G32B32A32_SFIXED,
+};
+
 static GLuint uint_types_direct[5] = {
    0,
    BRW_SURFACEFORMAT_R32_UINT,
@@ -215,8 +223,9 @@ static GLuint byte_types_scale[5] = {
  * the appopriate hardware surface type.
  * Format will be GL_RGBA or possibly GL_BGRA for GLubyte[4] color arrays.
  */
-static GLuint get_surface_type( GLenum type, GLuint size,
-                                GLenum format, bool normalized, bool integer )
+static unsigned
+get_surface_type(struct intel_context *intel, GLenum type, GLuint size,
+                 GLenum format, bool normalized, bool integer)
 {
    if (unlikely(INTEL_DEBUG & DEBUG_VERTS))
       printf("type %s size %d normalized %d\n", 
@@ -253,13 +262,25 @@ static GLuint get_surface_type( GLenum type, GLuint size,
             return ubyte_types_norm[size];
          }
       /* See GL_ARB_vertex_type_2_10_10_10_rev.
-       * W/A: the hardware doesn't really support the formats we'd
+       * W/A: Pre-Haswell, the hardware doesn't really support the formats we'd
        * like to use here, so upload everything as UINT and fix
        * it in the shader
        */
       case GL_INT_2_10_10_10_REV:
+         assert(size == 4);
+         if (intel->gen >= 8 || intel->is_haswell) {
+            return format == GL_BGRA
+               ? BRW_SURFACEFORMAT_B10G10R10A2_SNORM
+               : BRW_SURFACEFORMAT_R10G10B10A2_SNORM;
+         }
+         return BRW_SURFACEFORMAT_R10G10B10A2_UINT;
       case GL_UNSIGNED_INT_2_10_10_10_REV:
          assert(size == 4);
+         if (intel->gen >= 8 || intel->is_haswell) {
+            return format == GL_BGRA
+               ? BRW_SURFACEFORMAT_B10G10R10A2_UNORM
+               : BRW_SURFACEFORMAT_R10G10B10A2_UNORM;
+         }
          return BRW_SURFACEFORMAT_R10G10B10A2_UINT;
       default: assert(0); return 0;
       }
@@ -270,8 +291,21 @@ static GLuint get_surface_type( GLenum type, GLuint size,
        * like to use here, so upload everything as UINT and fix
        * it in the shader
        */
-      if (type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) {
+      if (type == GL_INT_2_10_10_10_REV) {
          assert(size == 4);
+         if (intel->gen >= 8 || intel->is_haswell) {
+            return format == GL_BGRA
+               ? BRW_SURFACEFORMAT_B10G10R10A2_SSCALED
+               : BRW_SURFACEFORMAT_R10G10B10A2_SSCALED;
+         }
+         return BRW_SURFACEFORMAT_R10G10B10A2_UINT;
+      } else if (type == GL_UNSIGNED_INT_2_10_10_10_REV) {
+         assert(size == 4);
+         if (intel->gen >= 8 || intel->is_haswell) {
+            return format == GL_BGRA
+               ? BRW_SURFACEFORMAT_B10G10R10A2_USCALED
+               : BRW_SURFACEFORMAT_R10G10B10A2_USCALED;
+         }
          return BRW_SURFACEFORMAT_R10G10B10A2_UINT;
       }
       assert(format == GL_RGBA); /* sanity check */
@@ -285,10 +319,14 @@ static GLuint get_surface_type( GLenum type, GLuint size,
       case GL_UNSIGNED_INT: return uint_types_scale[size];
       case GL_UNSIGNED_SHORT: return ushort_types_scale[size];
       case GL_UNSIGNED_BYTE: return ubyte_types_scale[size];
-      /* This produces GL_FIXED inputs as values between INT32_MIN and
-       * INT32_MAX, which will be scaled down by 1/65536 by the VS.
-       */
-      case GL_FIXED: return int_types_scale[size];
+      case GL_FIXED:
+         if (intel->gen >= 8 || intel->is_haswell)
+            return fixed_point_types[size];
+
+         /* This produces GL_FIXED inputs as values between INT32_MIN and
+          * INT32_MAX, which will be scaled down by 1/65536 by the VS.
+          */
+         return int_types_scale[size];
       default: assert(0); return 0;
       }
    }
@@ -659,7 +697,8 @@ static void brw_emit_vertices(struct brw_context *brw)
    OUT_BATCH((_3DSTATE_VERTEX_ELEMENTS << 16) | (2 * nr_elements - 1));
    for (i = 0; i < brw->vb.nr_enabled; i++) {
       struct brw_vertex_element *input = brw->vb.enabled[i];
-      uint32_t format = get_surface_type(input->glarray->Type,
+      uint32_t format = get_surface_type(intel,
+                                        input->glarray->Type,
                                         input->glarray->Size,
                                         input->glarray->Format,
                                         input->glarray->Normalized,
@@ -724,7 +763,8 @@ static void brw_emit_vertices(struct brw_context *brw)
    }
 
    if (intel->gen >= 6 && gen6_edgeflag_input) {
-      uint32_t format = get_surface_type(gen6_edgeflag_input->glarray->Type,
+      uint32_t format = get_surface_type(intel,
+                                        gen6_edgeflag_input->glarray->Type,
                                          gen6_edgeflag_input->glarray->Size,
                                          gen6_edgeflag_input->glarray->Format,
                                          gen6_edgeflag_input->glarray->Normalized,
index fc57f8a6727fb157cfe6f256bc6b3ad41aa539a2..0810471778194427b510c9e640272d2f2b27344d 100644 (file)
@@ -440,8 +440,14 @@ static void brw_upload_vs_prog(struct brw_context *brw)
    brw_populate_sampler_prog_key_data(ctx, prog, &key.tex);
 
    /* BRW_NEW_VERTICES */
-   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
-      if (vp->program.Base.InputsRead & BITFIELD64_BIT(i)) {
+   if (intel->gen < 8 && !intel->is_haswell) {
+      /* Prior to Haswell, the hardware can't natively support GL_FIXED or
+       * 2_10_10_10_REV vertex formats.  Set appropriate workaround flags.
+       */
+      for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+         if (!(vp->program.Base.InputsRead & BITFIELD64_BIT(i)))
+            continue;
+
          uint8_t wa_flags = 0;
 
          switch (brw->vb.inputs[i].glarray->Type) {