llvmpipe/draw: handle constant buffer limits and robustness (v1.1)
[mesa.git] / src / gallium / auxiliary / draw / draw_private.h
index db2e3c5410d8c054151ae3c6ef665a2ec230a338..05969faab73286bfb10fbb369e0d0cf2913ce077 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  * 
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2007 VMware, Inc.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,7 +18,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -32,7 +32,7 @@
 
 /**
  * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
+ * Keith Whitwell <keithw@vmware.com>
  * Brian Paul
  */
 
 
 #include "tgsi/tgsi_scan.h"
 
-#ifdef HAVE_LLVM
-#include <llvm-c/ExecutionEngine.h>
-struct draw_llvm;
+#ifdef LLVM_AVAILABLE
+struct gallivm_state;
 #endif
 
 
+/** Sum of frustum planes and user-defined planes */
+#define DRAW_TOTAL_CLIP_PLANES (6 + PIPE_MAX_CLIP_PLANES)
+
+/**
+ * The largest possible index of a vertex that can be fetched.
+ */
+#define DRAW_MAX_FETCH_IDX 0xffffffff
+
 struct pipe_context;
 struct draw_vertex_shader;
 struct draw_context;
@@ -59,19 +66,32 @@ struct draw_stage;
 struct vbuf_render;
 struct tgsi_exec_machine;
 struct tgsi_sampler;
+struct tgsi_image;
+struct tgsi_buffer;
+struct draw_pt_front_end;
+struct draw_assembler;
+struct draw_llvm;
+struct lp_cached_code;
 
+/**
+ * Represents the mapped vertex buffer.
+ */
+struct draw_vertex_buffer {
+   const void *map;
+   uint32_t size;
+};
 
 /**
  * Basic vertex info.
  * Carry some useful information around with the vertices in the prim pipe.  
  */
 struct vertex_header {
-   unsigned clipmask:12;
+   unsigned clipmask:DRAW_TOTAL_CLIP_PLANES;
    unsigned edgeflag:1;
-   unsigned pad:3;
+   unsigned pad:1;
    unsigned vertex_id:16;
 
-   float clip[4];
+   float clip_pos[4];
 
    /* This will probably become float (*data)[4] soon:
     */
@@ -83,7 +103,7 @@ struct vertex_header {
 
 
 /* maximum number of shader variants we can cache */
-#define DRAW_MAX_SHADER_VARIANTS 1024
+#define DRAW_MAX_SHADER_VARIANTS 512
 
 /**
  * Private context for the drawing module.
@@ -102,6 +122,7 @@ struct draw_context
       struct draw_stage *flatshade;
       struct draw_stage *clip;
       struct draw_stage *cull;
+      struct draw_stage *user_cull;
       struct draw_stage *twoside;
       struct draw_stage *offset;
       struct draw_stage *unfilled;
@@ -132,6 +153,14 @@ struct draw_context
    /* Support prototype passthrough path:
     */
    struct {
+      /* Current active frontend */
+      struct draw_pt_front_end *frontend;
+      unsigned prim;
+      unsigned opt;     /**< bitmask of PT_x flags */
+      unsigned eltSize; /* saved eltSize for flushing */
+      ubyte vertices_per_patch;
+      boolean rebind_parameters;
+
       struct {
          struct draw_pt_middle_end *fetch_emit;
          struct draw_pt_middle_end *fetch_shade_emit;
@@ -146,32 +175,55 @@ struct draw_context
       struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
       unsigned nr_vertex_buffers;
 
+      /*
+       * This is the largest legal index value for the current set of
+       * bound vertex buffers.  Regardless of any other consideration,
+       * all vertex lookups need to be clamped to 0..max_index to
+       * prevent out-of-bound access.
+       */
+      unsigned max_index;
+
       struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
       unsigned nr_vertex_elements;
 
-      struct pipe_index_buffer index_buffer;
-
       /* user-space vertex data, buffers */
       struct {
          /** vertex element/index buffer (ex: glDrawElements) */
          const void *elts;
          /** bytes per index (0, 1, 2 or 4) */
+         unsigned eltSizeIB;
          unsigned eltSize;
-         int eltBias;
+         unsigned eltMax;
+         int eltBias;         
          unsigned min_index;
          unsigned max_index;
+         unsigned drawid;
          
          /** vertex arrays */
-         const void *vbuffer[PIPE_MAX_ATTRIBS];
+         struct draw_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS];
          
          /** constant buffers (for vertex/geometry shader) */
          const void *vs_constants[PIPE_MAX_CONSTANT_BUFFERS];
          unsigned vs_constants_size[PIPE_MAX_CONSTANT_BUFFERS];
          const void *gs_constants[PIPE_MAX_CONSTANT_BUFFERS];
          unsigned gs_constants_size[PIPE_MAX_CONSTANT_BUFFERS];
-         
+         const void *tcs_constants[PIPE_MAX_CONSTANT_BUFFERS];
+         unsigned tcs_constants_size[PIPE_MAX_CONSTANT_BUFFERS];
+         const void *tes_constants[PIPE_MAX_CONSTANT_BUFFERS];
+         unsigned tes_constants_size[PIPE_MAX_CONSTANT_BUFFERS];
+
+         /** shader buffers (for vertex/geometry shader) */
+         const void *vs_ssbos[PIPE_MAX_SHADER_BUFFERS];
+         unsigned vs_ssbos_size[PIPE_MAX_SHADER_BUFFERS];
+         const void *gs_ssbos[PIPE_MAX_SHADER_BUFFERS];
+         unsigned gs_ssbos_size[PIPE_MAX_SHADER_BUFFERS];
+         const void *tcs_ssbos[PIPE_MAX_SHADER_BUFFERS];
+         unsigned tcs_ssbos_size[PIPE_MAX_SHADER_BUFFERS];
+         const void *tes_ssbos[PIPE_MAX_SHADER_BUFFERS];
+         unsigned tes_ssbos_size[PIPE_MAX_SHADER_BUFFERS];
+
          /* pointer to planes */
-         float (*planes)[12][4]; 
+         float (*planes)[DRAW_TOTAL_CLIP_PLANES][4]; 
       } user;
 
       boolean test_fse;         /* enable FSE even though its not correct (eg for softpipe) */
@@ -181,8 +233,12 @@ struct draw_context
    struct {
       boolean bypass_clip_xy;
       boolean bypass_clip_z;
+      boolean guard_band_xy;
+      boolean bypass_clip_points;
    } driver;
 
+   boolean quads_always_flatshade_last;
+
    boolean flushing;         /**< debugging/sanity */
    boolean suspend_flushing; /**< internally set */
 
@@ -192,11 +248,15 @@ struct draw_context
    boolean clip_xy;
    boolean clip_z;
    boolean clip_user;
+   boolean guard_band_xy;
+   boolean guard_band_points_xy;
 
    boolean force_passthrough; /**< never clip or shade */
 
    boolean dump_vs;
 
+   /** Depth format and bias related settings. */
+   boolean floating_point_depth;
    double mrd;  /**< minimum resolvable depth value, for polygon offset */
 
    /** Current rasterizer state given to us by the driver */
@@ -207,8 +267,9 @@ struct draw_context
    /** Rasterizer CSOs without culling/stipple/etc */
    void *rasterizer_no_cull[2][2];
 
-   struct pipe_viewport_state viewport;
+   struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
    boolean identity_viewport;
+   boolean bypass_viewport;
 
    /** Vertex shader state */
    struct {
@@ -216,23 +277,17 @@ struct draw_context
       uint num_vs_outputs;  /**< convenience, from vertex_shader */
       uint position_output;
       uint edgeflag_output;
+      uint clipvertex_output;
+      uint ccdistance_output[2];
 
-      /** TGSI program interpreter runtime state */
-      struct tgsi_exec_machine *machine;
-
-      uint num_samplers;
-      struct tgsi_sampler **samplers;
-
-      /* Here's another one:
-       */
-      struct aos_machine *aos_machine; 
-
-
-      const void *aligned_constants[PIPE_MAX_CONSTANT_BUFFERS];
-
-      const void *aligned_constant_storage[PIPE_MAX_CONSTANT_BUFFERS];
-      unsigned const_storage_size[PIPE_MAX_CONSTANT_BUFFERS];
+      /** Fields for TGSI interpreter / execution */
+      struct {
+         struct tgsi_exec_machine *machine;
 
+         struct tgsi_sampler *sampler;
+         struct tgsi_image *image;
+         struct tgsi_buffer *buffer;
+      } tgsi;
 
       struct translate *fetch;
       struct translate_cache *fetch_cache;
@@ -246,13 +301,45 @@ struct draw_context
       uint num_gs_outputs;  /**< convenience, from geometry_shader */
       uint position_output;
 
-      /** TGSI program interpreter runtime state */
-      struct tgsi_exec_machine *machine;
+      /** Fields for TGSI interpreter / execution */
+      struct {
+         struct tgsi_exec_machine *machine;
+
+         struct tgsi_sampler *sampler;
+         struct tgsi_image *image;
+         struct tgsi_buffer *buffer;
+      } tgsi;
 
-      uint num_samplers;
-      struct tgsi_sampler **samplers;
    } gs;
 
+   /* Tessellation state */
+   struct {
+      struct draw_tess_ctrl_shader *tess_ctrl_shader;
+
+      /** Fields for TGSI interpreter / execution */
+      struct {
+         struct tgsi_exec_machine *machine;
+
+         struct tgsi_sampler *sampler;
+         struct tgsi_image *image;
+         struct tgsi_buffer *buffer;
+      } tgsi;
+   } tcs;
+
+   struct {
+      struct draw_tess_eval_shader *tess_eval_shader;
+      uint position_output;
+
+      /** Fields for TGSI interpreter / execution */
+      struct {
+         struct tgsi_exec_machine *machine;
+
+         struct tgsi_sampler *sampler;
+         struct tgsi_image *image;
+         struct tgsi_buffer *buffer;
+      } tgsi;
+   } tes;
+
    /** Fragment shader state */
    struct {
       struct draw_fragment_shader *fragment_shader;
@@ -260,16 +347,13 @@ struct draw_context
 
    /** Stream output (vertex feedback) state */
    struct {
-      struct pipe_stream_output_state state;
-      void *buffers[PIPE_MAX_SO_BUFFERS];
-      uint num_buffers;
+      struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS];
+      uint num_targets;
    } so;
 
    /* Clip derived state:
     */
-   float plane[12][4];
-   unsigned nr_planes;
-   boolean depth_clamp;
+   float plane[DRAW_TOTAL_CLIP_PLANES][4];
 
    /* If a prim stage introduces new vertex attributes, they'll be stored here
     */
@@ -280,19 +364,41 @@ struct draw_context
       uint slot[10];
    } extra_shader_outputs;
 
-   unsigned reduced_prim;
-
    unsigned instance_id;
-
-#ifdef HAVE_LLVM
+   unsigned start_instance;
+   unsigned start_index;
+   unsigned constant_buffer_stride;
    struct draw_llvm *llvm;
-   struct gallivm_state *own_gallivm;
-#endif
 
-   struct pipe_sampler_view *sampler_views[PIPE_MAX_VERTEX_SAMPLERS];
-   unsigned num_sampler_views;
-   const struct pipe_sampler_state *samplers[PIPE_MAX_VERTEX_SAMPLERS];
-   unsigned num_samplers;
+   /** Texture sampler and sampler view state.
+    * Note that we have arrays indexed by shader type.  At this time
+    * we only handle vertex and geometry shaders in the draw module, but
+    * there may be more in the future (ex: hull and tessellation).
+    */
+   struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
+   unsigned num_sampler_views[PIPE_SHADER_TYPES];
+   const struct pipe_sampler_state *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
+   unsigned num_samplers[PIPE_SHADER_TYPES];
+
+   struct pipe_image_view *images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES];
+   unsigned num_images[PIPE_SHADER_TYPES];
+
+   struct pipe_query_data_pipeline_statistics statistics;
+   boolean collect_statistics;
+
+   float default_outer_tess_level[4];
+   float default_inner_tess_level[2];
+   bool collect_primgen;
+
+   struct draw_assembler *ia;
+
+   void *disk_cache_cookie;
+   void (*disk_cache_find_shader)(void *cookie,
+                                  struct lp_cached_code *cache,
+                                  unsigned char ir_sha1_cache_key[20]);
+   void (*disk_cache_insert_shader)(void *cookie,
+                                    struct lp_cached_code *cache,
+                                    unsigned char ir_sha1_cache_key[20]);
 
    void *driver_private;
 };
@@ -313,8 +419,9 @@ struct draw_vertex_info {
 };
 
 /* these flags are set if the primitive is a segment of a larger one */
-#define DRAW_SPLIT_BEFORE 0x1
-#define DRAW_SPLIT_AFTER  0x2
+#define DRAW_SPLIT_BEFORE        0x1
+#define DRAW_SPLIT_AFTER         0x2
+#define DRAW_LINE_LOOP_AS_STRIP  0x4
 
 struct draw_prim_info {
    boolean linear;
@@ -334,6 +441,7 @@ struct draw_prim_info {
  * Draw common initialization code
  */
 boolean draw_init(struct draw_context *draw);
+void draw_new_instance(struct draw_context *draw);
 
 /*******************************************************************************
  * Vertex shader code:
@@ -341,27 +449,12 @@ boolean draw_init(struct draw_context *draw);
 boolean draw_vs_init( struct draw_context *draw );
 void draw_vs_destroy( struct draw_context *draw );
 
-void draw_vs_set_viewport( struct draw_context *, 
-                           const struct pipe_viewport_state * );
-
-void
-draw_vs_set_constants(struct draw_context *,
-                      unsigned slot,
-                      const void *constants,
-                      unsigned size);
-
-
 
 /*******************************************************************************
  * Geometry shading code:
  */
 boolean draw_gs_init( struct draw_context *draw );
 
-void
-draw_gs_set_constants(struct draw_context *,
-                      unsigned slot,
-                      const void *constants,
-                      unsigned size);
 
 void draw_gs_destroy( struct draw_context *draw );
 
@@ -370,10 +463,16 @@ void draw_gs_destroy( struct draw_context *draw );
  */
 uint draw_current_shader_outputs(const struct draw_context *draw);
 uint draw_current_shader_position_output(const struct draw_context *draw);
-
+uint draw_current_shader_viewport_index_output(const struct draw_context *draw);
+uint draw_current_shader_clipvertex_output(const struct draw_context *draw);
+uint draw_current_shader_ccdistance_output(const struct draw_context *draw, int index);
+uint draw_current_shader_num_written_clipdistances(const struct draw_context *draw);
+uint draw_current_shader_num_written_culldistances(const struct draw_context *draw);
 int draw_alloc_extra_vertex_attrib(struct draw_context *draw,
                                    uint semantic_name, uint semantic_index);
 void draw_remove_extra_vertex_attribs(struct draw_context *draw);
+boolean draw_current_shader_uses_viewport_index(
+   const struct draw_context *draw);
 
 
 /*******************************************************************************
@@ -382,6 +481,7 @@ void draw_remove_extra_vertex_attribs(struct draw_context *draw);
 boolean draw_pt_init( struct draw_context *draw );
 void draw_pt_destroy( struct draw_context *draw );
 void draw_pt_reset_vertex_ids( struct draw_context *draw );
+void draw_pt_flush( struct draw_context *draw, unsigned flags );
 
 
 /*******************************************************************************
@@ -425,8 +525,9 @@ void draw_pipeline_flush( struct draw_context *draw,
  * Flushing 
  */
 
-#define DRAW_FLUSH_STATE_CHANGE              0x8
-#define DRAW_FLUSH_BACKEND                   0x10
+#define DRAW_FLUSH_PARAMETER_CHANGE 0x1  /**< Constants, viewport, etc */
+#define DRAW_FLUSH_STATE_CHANGE     0x2  /**< Other/heavy state changes */
+#define DRAW_FLUSH_BACKEND          0x4  /**< Flush the output buffer */
 
 
 void draw_do_flush( struct draw_context *draw, unsigned flags );
@@ -438,5 +539,44 @@ draw_get_rasterizer_no_cull( struct draw_context *draw,
                              boolean scissor,
                              boolean flatshade );
 
+void
+draw_stats_clipper_primitives(struct draw_context *draw,
+                              const struct draw_prim_info *prim_info);
+
+void draw_update_clip_flags(struct draw_context *draw);
+void draw_update_viewport_flags(struct draw_context *draw);
+
+/** 
+ * Return index i from the index buffer.
+ * If the index buffer would overflow we return index 0.
+ */
+#define DRAW_GET_IDX(_elts, _i)                   \
+   (((_i) >= draw->pt.user.eltMax) ? 0 : (_elts)[_i])
+
+/**
+ * Return index of the given viewport clamping it
+ * to be between 0 <= and < PIPE_MAX_VIEWPORTS
+ */
+static inline unsigned
+draw_clamp_viewport_idx(int idx)
+{
+   return ((PIPE_MAX_VIEWPORTS > idx && idx >= 0) ? idx : 0);
+}
+
+/**
+ * Adds two unsigned integers and if the addition
+ * overflows then it returns the value from
+ * the overflow_value variable.
+ */
+static inline unsigned
+draw_overflow_uadd(unsigned a, unsigned b,
+                   unsigned overflow_value)
+{
+   unsigned res = a + b;
+   if (res < a) {
+      res = overflow_value;
+   }
+   return res;
+}
 
 #endif /* DRAW_PRIVATE_H */