gallivm: implement switch opcode
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_tgsi.h
index 773c679a4d838d94848a70395e89fa20bd87ac77..9d9c742e9a3fd424f2018f237e7f11a09a286b85 100644 (file)
@@ -60,6 +60,8 @@ struct tgsi_token;
 struct tgsi_shader_info;
 struct lp_build_mask_context;
 struct gallivm_state;
+struct lp_derivatives;
+struct lp_build_tgsi_gs_iface;
 
 
 enum lp_build_tex_modifier {
@@ -67,7 +69,8 @@ enum lp_build_tex_modifier {
    LP_BLD_TEX_MODIFIER_PROJECTED,
    LP_BLD_TEX_MODIFIER_LOD_BIAS,
    LP_BLD_TEX_MODIFIER_EXPLICIT_LOD,
-   LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV
+   LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV,
+   LP_BLD_TEX_MODIFIER_LOD_ZERO
 };
 
 
@@ -103,7 +106,8 @@ struct lp_tgsi_texture_info
 {
    struct lp_tgsi_channel_info coord[4];
    unsigned target:8; /* TGSI_TEXTURE_* */
-   unsigned unit:8;  /* Sampler unit */
+   unsigned sampler_unit:8;  /* Sampler unit */
+   unsigned texture_unit:8;  /* Texture unit */
    unsigned modifier:8; /* LP_BLD_TEX_MODIFIER_* */
 };
 
@@ -145,6 +149,16 @@ struct lp_tgsi_info
    const struct lp_tgsi_channel_info *cbuf[PIPE_MAX_COLOR_BUFS];
 };
 
+/**
+ * Reference to system values.
+ */
+struct lp_bld_tgsi_system_values {
+   LLVMValueRef instance_id;
+   LLVMValueRef vertex_id;
+   LLVMValueRef prim_id;
+};
+
+
 /**
  * Sampler code generation interface.
  *
@@ -162,14 +176,24 @@ struct lp_build_sampler_soa
    (*emit_fetch_texel)( const struct lp_build_sampler_soa *sampler,
                         struct gallivm_state *gallivm,
                         struct lp_type type,
-                        unsigned unit,
-                        unsigned num_coords,
+                        boolean is_fetch,
+                        unsigned texture_index,
+                        unsigned sampler_index,
                         const LLVMValueRef *coords,
-                        const LLVMValueRef *ddx,
-                        const LLVMValueRef *ddy,
+                        const LLVMValueRef *offsets,
+                        const struct lp_derivatives *derivs,
                         LLVMValueRef lod_bias, /* optional */
                         LLVMValueRef explicit_lod, /* optional */
                         LLVMValueRef *texel);
+
+   void
+   (*emit_size_query)( const struct lp_build_sampler_soa *sampler,
+                       struct gallivm_state *gallivm,
+                       struct lp_type type,
+                       unsigned unit,
+                       boolean need_nr_mips,
+                       LLVMValueRef explicit_lod, /* optional */
+                       LLVMValueRef *sizes_out);
 };
 
 
@@ -181,8 +205,7 @@ struct lp_build_sampler_aos
                         unsigned target, /* TGSI_TEXTURE_* */
                         unsigned unit,
                         LLVMValueRef coords,
-                        LLVMValueRef ddx,
-                        LLVMValueRef ddy,
+                        const struct lp_derivatives derivs,
                         enum lp_build_tex_modifier modifier);
 };
 
@@ -198,12 +221,12 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
                   struct lp_type type,
                   struct lp_build_mask_context *mask,
                   LLVMValueRef consts_ptr,
-                  LLVMValueRef system_values_array,
-                  const LLVMValueRef *pos,
+                  const struct lp_bld_tgsi_system_values *system_values,
                   const LLVMValueRef (*inputs)[4],
                   LLVMValueRef (*outputs)[4],
                   struct lp_build_sampler_soa *sampler,
-                  const struct tgsi_shader_info *info);
+                  const struct tgsi_shader_info *info,
+                  const struct lp_build_tgsi_gs_iface *gs_iface);
 
 
 void
@@ -218,17 +241,17 @@ lp_build_tgsi_aos(struct gallivm_state *gallivm,
                   const struct tgsi_shader_info *info);
 
 
-LLVMValueRef
-lp_build_system_values_array(struct gallivm_state *gallivm,
-                             const struct tgsi_shader_info *info,
-                             LLVMValueRef instance_id,
-                             LLVMValueRef facing);
+enum lp_exec_mask_break_type {
+   LP_EXEC_MASK_BREAK_TYPE_LOOP,
+   LP_EXEC_MASK_BREAK_TYPE_SWITCH
+};
 
 
 struct lp_exec_mask {
    struct lp_build_context *bld;
 
    boolean has_mask;
+   boolean ret_in_main;
 
    LLVMTypeRef int_vec_type;
 
@@ -236,6 +259,24 @@ struct lp_exec_mask {
    int cond_stack_size;
    LLVMValueRef cond_mask;
 
+   /* keep track if break belongs to switch or loop */
+   enum lp_exec_mask_break_type break_type_stack[LP_MAX_TGSI_NESTING];
+   enum lp_exec_mask_break_type break_type;
+
+   struct {
+      LLVMValueRef switch_val;
+      LLVMValueRef switch_mask;
+      LLVMValueRef switch_mask_default;
+      boolean switch_in_default;
+      unsigned switch_pc;
+   } switch_stack[LP_MAX_TGSI_NESTING];
+   int switch_stack_size;
+   LLVMValueRef switch_val;
+   LLVMValueRef switch_mask;         /* current switch exec mask */
+   LLVMValueRef switch_mask_default; /* reverse of switch mask used for default */
+   boolean switch_in_default;        /* if switch exec is currently in default */
+   unsigned switch_pc;               /* when used points to default or endswitch-1 */
+
    LLVMBasicBlockRef loop_block;
    LLVMValueRef cont_mask;
    LLVMValueRef break_mask;
@@ -298,6 +339,8 @@ struct lp_build_tgsi_context
     * should compute 1 / sqrt (src0.x) */
    struct lp_build_tgsi_action rsq_action;
 
+   struct lp_build_tgsi_action sqrt_action;
+
    const struct tgsi_shader_info *info;
 
    lp_build_emit_fetch_fn emit_fetch_funcs[TGSI_FILE_COUNT];
@@ -344,6 +387,28 @@ struct lp_build_tgsi_context
    void (*emit_epilogue)(struct lp_build_tgsi_context*);
 };
 
+struct lp_build_tgsi_gs_iface
+{
+   LLVMValueRef (*fetch_input)(const struct lp_build_tgsi_gs_iface *gs_iface,
+                               struct lp_build_tgsi_context * bld_base,
+                               boolean is_indirect,
+                               LLVMValueRef vertex_index,
+                               LLVMValueRef attrib_index,
+                               LLVMValueRef swizzle_index);
+   void (*emit_vertex)(const struct lp_build_tgsi_gs_iface *gs_iface,
+                       struct lp_build_tgsi_context * bld_base,
+                       LLVMValueRef (*outputs)[4],
+                       LLVMValueRef emitted_vertices_vec);
+   void (*end_primitive)(const struct lp_build_tgsi_gs_iface *gs_iface,
+                         struct lp_build_tgsi_context * bld_base,
+                         LLVMValueRef verts_per_prim_vec,
+                         LLVMValueRef emitted_prims_vec);
+   void (*gs_epilogue)(const struct lp_build_tgsi_gs_iface *gs_iface,
+                       struct lp_build_tgsi_context * bld_base,
+                       LLVMValueRef total_emitted_vertices_vec,
+                       LLVMValueRef emitted_prims_vec);
+};
+
 struct lp_build_tgsi_soa_context
 {
    struct lp_build_tgsi_context bld_base;
@@ -351,13 +416,20 @@ struct lp_build_tgsi_soa_context
    /* Builder for scalar elements of shader's data type (float) */
    struct lp_build_context elem_bld;
 
+   const struct lp_build_tgsi_gs_iface *gs_iface;
+   LLVMValueRef emitted_prims_vec_ptr;
+   LLVMValueRef total_emitted_vertices_vec_ptr;
+   LLVMValueRef emitted_vertices_vec_ptr;
+   LLVMValueRef max_output_vertices_vec;
+
    LLVMValueRef consts_ptr;
-   const LLVMValueRef *pos;
    const LLVMValueRef (*inputs)[TGSI_NUM_CHANNELS];
    LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS];
 
    const struct lp_build_sampler_soa *sampler;
 
+   struct tgsi_declaration_sampler_view sv[PIPE_MAX_SHADER_SAMPLER_VIEWS];
+
    LLVMValueRef immediates[LP_MAX_TGSI_IMMEDIATES][TGSI_NUM_CHANNELS];
    LLVMValueRef temps[LP_MAX_TGSI_TEMPS][TGSI_NUM_CHANNELS];
    LLVMValueRef addr[LP_MAX_TGSI_ADDRS][TGSI_NUM_CHANNELS];
@@ -381,7 +453,7 @@ struct lp_build_tgsi_soa_context
     */
    LLVMValueRef inputs_array;
 
-   LLVMValueRef system_values_array;
+   struct lp_bld_tgsi_system_values system_values;
 
    /** bitmask indicating which register files are accessed indirectly */
    unsigned indirect_files;
@@ -546,6 +618,14 @@ lp_build_emit_fetch(
    unsigned src_op,
    const unsigned chan_index);
 
+
+LLVMValueRef
+lp_build_emit_fetch_texoffset(
+   struct lp_build_tgsi_context *bld_base,
+   const struct tgsi_full_instruction *inst,
+   unsigned tex_off_op,
+   const unsigned chan_index);
+
 boolean
 lp_build_tgsi_llvm(
    struct lp_build_tgsi_context * bld_base,